Add files for the new one.

Rework UI from scratch with proper themes and custom controls. MDI windows are now used for workspaces, comparing docs, and multiple usages. Tabs organise multiple workspaces and you can keep mdi windows maximized if you want to only use tabs. Themes currently include dark and white theme but plan to have XML files with list of color and styles
Alot of things optimized. UI is very fast and snappy now
Dae rigging fixed.
Dae bones can be imported.
Dae with textures can be imported and exported to a folder
Custom sampler editor for sampler data.
Texture refs, shader options, params, render info, and basically all material data can be added/removed and edited
User data editor
Update opengl framework by JuPaHe64 to the newest. Includes an origintation cube, multiple models in a scene, and many improvements
Skeleton can be viewed
GFPAK with some fixes in saving
NUTEXB has proper mip map viewing
PTCL Editor (Wii U and Switch). Can edit colors ( Wii U) and view textures. Also EFFN files in smash ultimate can be previewed
Files can be associated with the program and opened with on clicking them
ASTC textures can be viewed
UVs can be viewed. Includes wrap modes and also translating and scaling for some basic edits
Textures use a new editor. It includes channel viewing and some new editing options
Fixed black textures on some wii u bfres
Fixed saving sarcs in sarcs
Shortcut keys have been added in. CTRL + S can save the active file in the currently used window
Fix more issues with bfres crashing
File - New includes BNTX for creating new bntx files from scatch
Raw shader binaries can be extracted from bnsh and bfsha. Yuzu and Ryujinx can decompile these
Sharc files can have source data previewed and shader programs in XML
Aamp v1 and v2 data can be previewed. v1 can be edited and saved atm, v2 will be at a later update
Byaml uses it's own editor instead of a seperate window for easy saving within sarcs
Archives have a hex viewer
Dae exporting greatly improved and can export rigged meshes
Scene, shader param, srt, color, and texture pattern animations can all be previewed (in a list)
Memory usage is greatly improved
Narc (Nitro Archives) can be viewed and extracted.
Fixed importing TGA images
Support importing ASTC textures for bntx
Added in PBR lighting for bfres from my implimentaion in forge
Added gradient background for viewport. This can be edited in the settings
Added skybox background option for viewport. Can load cubemaps
Added grid with customizable cells for viewport.
DDS decompression no longer requires Direct X tex.
Zlib decompression has been improved for opening files that use it
Rigid bones are properly ordered on importing a mesh. May fix some exploding issues.
Endianness for KCL can be toggled for saving. Will be set to what it was using orignally
Tangents can be filled with a constant value. Will allow them to not cause seams nor flat lighting however normal maps may not work as good
Vertex buffers can be added and removed. Also re encoded
Parameters now use drop down panels with values for easier editing
Reworked the bone editor. Everything for a bone can be fully edited now besides the index, billboard index and parent index  which get set automatically
Fixed animation scaling for skeletal animations finally!
Textures can be loaded in a tab now with thumbnail displaying for easy real time edits while previewing in the viewport

Fixed support for audio files to be big endian in BARS
Textures for switch now use their own folder. You can easily add textures to this and add textures to bfres that have no bntx. If there are no textures then the bfres will automatically not have one on save.
Animations are split into multiple sub sections for switch's material animation for easier access
Bfres for wii u has better binary exporting and is fully compatiable with Wexos Toolbox (to and from)
Every section can be added in as new for both wii u and switch.
Every section can be renamed properly and mostly everything can be edited. (Key frame editing and a more in depth curve editor later)
Added option to copy UV channel
Bone weights can be previewed
Tons of fixes for the switch bfres library with more games working. Splatoon 2 (more work now), BOTW, Kirby Star Allies, and more!
Fixed 3.3 Wii U bfres from not opening
Wii U Sharcfb files can have shader program data previewed (XML)

And possibly alot more things i missed! All this is still experimental but will improve over the next few weeks
This commit is contained in:
KillzXGaming 2019-03-23 12:55:09 -04:00
parent 00875d5aec
commit d1f03b161f
1392 changed files with 387275 additions and 0 deletions

BIN
.vs/Switch_Toolbox/v15/.suo Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

261
GL_EditorFramework-master/.gitignore vendored Normal file
View file

@ -0,0 +1,261 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
project.fragment.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

View file

@ -0,0 +1,31 @@

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}") = "Gl_EditorFramework", "Gl_EditorFramework\Gl_EditorFramework.csproj", "{D593A72D-554D-40FB-9967-503CB15A744F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testing", "Testing\Testing.csproj", "{860B49C9-54E3-4E10-830D-6497B845ED11}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D593A72D-554D-40FB-9967-503CB15A744F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D593A72D-554D-40FB-9967-503CB15A744F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D593A72D-554D-40FB-9967-503CB15A744F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D593A72D-554D-40FB-9967-503CB15A744F}.Release|Any CPU.Build.0 = Release|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{860B49C9-54E3-4E10-830D-6497B845ED11}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DF396B96-389A-48D7-8A82-0D3C500F744D}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,71 @@
using GL_EditorFramework.GL_Core;
using GL_EditorFramework.Interfaces;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GL_EditorFramework.EditorDrawables
{
public abstract class EditableObject : AbstractGlDrawable
{
public static Vector4 hoverColor = new Vector4(1, 1, 0.925f,1);
public static Vector4 selectColor = new Vector4(1, 1, 0.675f, 1);
[Browsable(false)]
public bool Visible = true;
public EditableObject()
{
}
//only gets called when the object is selected
public abstract bool CanStartDragging();
public abstract bool IsSelected();
public abstract Vector3 GetSelectionCenter();
public abstract uint SelectAll(I3DControl control);
public abstract uint SelectDefault(I3DControl control);
public virtual void Draw(GL_ControlModern control, Pass pass, EditorScene editorScene)
{
}
public virtual void Draw(GL_ControlLegacy control, Pass pass, EditorScene editorScene)
{
}
public abstract uint Select(int partIndex, I3DControl control);
public abstract uint Deselect(int partIndex, I3DControl control);
public abstract uint DeselectAll(I3DControl control);
public abstract void ApplyTransformationToSelection(DeltaTransform deltaTransform);
public struct DeltaTransform
{
public Vector3 Translation;
public Quaternion Rotation;
public Vector3 Scaling;
public DeltaTransform(Vector3 Translation, Quaternion Rotation, Vector3 Scaling)
{
this.Translation = Translation;
this.Rotation = Rotation;
this.Scaling = Scaling;
}
}
}
}

View file

@ -0,0 +1,604 @@
using GL_EditorFramework.GL_Core;
using GL_EditorFramework.Interfaces;
using OpenTK;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GL_EditorFramework.EditorDrawables
{
public class EditorScene : AbstractGlDrawable
{
protected bool multiSelect;
public EditableObject hovered = null;
public int hoveredPart = 0;
public List<EditableObject> objects = new List<EditableObject>();
protected List<EditableObject> selectedObjects = new List<EditableObject>();
public List<AbstractGlDrawable> staticObjects = new List<AbstractGlDrawable>();
public event EventHandler SelectionChanged;
private float draggingDepth;
private GL_ControlBase control;
public EditableObject.DeltaTransform deltaTransform = new EditableObject.DeltaTransform(new Vector3(), new Quaternion(), new Vector3(1,1,1));
public EditorScene(bool multiSelect = true)
{
this.multiSelect = multiSelect;
}
public List<EditableObject> SelectedObjects
{
get => selectedObjects;
set
{
uint var = 0;
foreach (EditableObject obj in value)
{
if (!selectedObjects.Contains(obj)) //object wasn't selected before
var |= obj.SelectDefault(control); //select it
else //object stays selected
selectedObjects.Remove(obj); //filter out these to find all objects which are not selected anymore
Console.WriteLine(obj);
}
foreach (EditableObject obj in selectedObjects) //now the selected objects are a list of objects to deselect
//which is fine because in the end they get overwriten anyway
{
var |= obj.DeselectAll(control); //Deselect them all
}
selectedObjects = value;
if ((var & AbstractGlDrawable.REDRAW)>0)
control.Refresh();
if ((var & AbstractGlDrawable.REDRAW_PICKING) > 0)
control.DrawPicking();
}
}
public void ToogleSelected(EditableObject obj, bool isSelected)
{
uint var = 0;
bool alreadySelected = selectedObjects.Contains(obj);
if(alreadySelected && !isSelected)
{
var |= obj.DeselectAll(control);
selectedObjects.Remove(obj);
}
else if(!alreadySelected && isSelected)
{
var |= obj.SelectDefault(control);
selectedObjects.Add(obj);
}
if ((var & AbstractGlDrawable.REDRAW)>0)
control.Refresh();
if ((var & AbstractGlDrawable.REDRAW_PICKING) > 0)
control.DrawPicking();
}
public void Add(params EditableObject[] objs)
{
uint var = 0;
foreach (EditableObject selected in selectedObjects)
{
var |= selected.DeselectAll(control);
}
selectedObjects.Clear();
foreach (EditableObject obj in objs)
{
objects.Add(obj);
selectedObjects.Add(obj);
var |= obj.SelectDefault(control);
}
SelectionChanged?.Invoke(this, new EventArgs());
if ((var & AbstractGlDrawable.REDRAW) > 0)
control.Refresh();
if ((var & AbstractGlDrawable.REDRAW_PICKING) > 0)
control.DrawPicking();
}
public void Delete(params EditableObject[] objs)
{
uint var = 0;
bool selectionHasChanged = false;
foreach (EditableObject obj in objs)
{
objects.Remove(obj);
if (selectedObjects.Contains(obj))
{
var |= obj.DeselectAll(control);
selectedObjects.Remove(obj);
}
}
if(selectionHasChanged)
SelectionChanged?.Invoke(this, new EventArgs());
if ((var & AbstractGlDrawable.REDRAW) > 0)
control.Refresh();
if ((var & AbstractGlDrawable.REDRAW_PICKING) > 0)
control.DrawPicking();
}
public void InsertAfter(int index, params EditableObject[] objs)
{
uint var = 0;
foreach (EditableObject selected in selectedObjects)
{
var |= selected.DeselectAll(control);
}
selectedObjects.Clear();
foreach (EditableObject obj in objs)
{
objects.Insert(index, obj);
selectedObjects.Add(obj);
var |= obj.SelectDefault(control);
index++;
}
SelectionChanged?.Invoke(this, new EventArgs());
if ((var & AbstractGlDrawable.REDRAW) > 0)
control.Refresh();
if ((var & AbstractGlDrawable.REDRAW_PICKING) > 0)
control.DrawPicking();
}
public override void Draw(GL_ControlModern control, Pass pass)
{
foreach (EditableObject obj in objects)
{
if(obj.Visible)
obj.Draw(control, pass, this);
}
foreach (AbstractGlDrawable obj in staticObjects)
{
obj.Draw(control, pass);
}
}
public override void Draw(GL_ControlLegacy control, Pass pass)
{
foreach (EditableObject obj in objects)
{
if (obj.Visible)
obj.Draw(control, pass, this);
}
foreach (AbstractGlDrawable obj in staticObjects)
{
obj.Draw(control, pass);
}
}
public override void Prepare(GL_ControlModern control)
{
this.control = control;
foreach (EditableObject obj in objects)
obj.Prepare(control);
foreach (AbstractGlDrawable obj in staticObjects)
obj.Prepare(control);
}
public override void Prepare(GL_ControlLegacy control)
{
this.control = control;
foreach (EditableObject obj in objects)
obj.Prepare(control);
foreach (AbstractGlDrawable obj in staticObjects)
obj.Prepare(control);
}
public override uint MouseDown(MouseEventArgs e, I3DControl control)
{
uint var = 0;
if (draggingDepth == -1 && e.Button == MouseButtons.Left && selectedObjects.Contains(hovered))
{
if(hovered.CanStartDragging())
draggingDepth = control.PickingDepth;
}
foreach (EditableObject obj in objects)
{
var |= obj.MouseDown(e, control);
}
foreach (AbstractGlDrawable obj in staticObjects)
{
var |= obj.MouseDown(e, control);
}
return var;
}
public override uint MouseMove(MouseEventArgs e, Point lastMousePos, I3DControl control)
{
uint var = 0;
foreach (EditableObject obj in objects)
{
var |= obj.MouseMove(e, lastMousePos, control);
}
foreach (AbstractGlDrawable obj in staticObjects)
{
var |= obj.MouseMove(e, lastMousePos, control);
}
if (draggingDepth != -1)
{
Vector3 translation = new Vector3();
//code from Whitehole
float deltaX = e.X - control.DragStartPos.X;
float deltaY = e.Y - control.DragStartPos.Y;
deltaX *= draggingDepth * control.FactorX;
deltaY *= draggingDepth * control.FactorY;
translation += Vector3.UnitX * deltaX * (float)Math.Cos(control.CamRotX);
translation -= Vector3.UnitX * deltaY * (float)Math.Sin(control.CamRotX) * (float)Math.Sin(control.CamRotY);
translation -= Vector3.UnitY * deltaY * (float)Math.Cos(control.CamRotY);
translation += Vector3.UnitZ * deltaX * (float)Math.Sin(control.CamRotX);
translation += Vector3.UnitZ * deltaY * (float)Math.Cos(control.CamRotX) * (float)Math.Sin(control.CamRotY);
deltaTransform.Translation = translation;
var |= REDRAW | NO_CAMERA_ACTION;
var &= ~REPICK;
}
else
{
var |= REPICK;
}
return var;
}
public override uint MouseUp(MouseEventArgs e, I3DControl control)
{
uint var = 0;
if (!(draggingDepth == -1)&&e.Button == MouseButtons.Left)
{
foreach (EditableObject obj in selectedObjects)
{
obj.ApplyTransformationToSelection(deltaTransform);
}
deltaTransform = new EditableObject.DeltaTransform(new Vector3(), new Quaternion(), new Vector3(1, 1, 1));
}
foreach (EditableObject obj in objects)
{
var |= obj.MouseUp(e, control);
}
foreach (AbstractGlDrawable obj in staticObjects)
{
var |= obj.MouseUp(e, control);
}
draggingDepth = -1;
return var;
}
public override uint MouseClick(MouseEventArgs e, I3DControl control)
{
uint var = 0;
foreach (EditableObject obj in objects)
{
var |= obj.MouseClick(e, control);
}
foreach (AbstractGlDrawable obj in staticObjects)
{
var |= obj.MouseClick(e, control);
}
if (!(e.Button == MouseButtons.Left))
return var;
if (!(multiSelect && OpenTK.Input.Keyboard.GetState().IsKeyDown(OpenTK.Input.Key.ShiftLeft)))
{
if (multiSelect)
{
if (!selectedObjects.Contains(hovered))
{
foreach (EditableObject selected in selectedObjects)
{
selected.DeselectAll(control);
}
}
if (hovered != null && !selectedObjects.Contains(hovered))
{
selectedObjects.Clear();
selectedObjects.Add(hovered);
hovered.Select(hoveredPart,control);
SelectionChanged?.Invoke(this, new EventArgs());
}
else if(hovered == null)
{
selectedObjects.Clear();
SelectionChanged?.Invoke(this, new EventArgs());
}
}
else
{
foreach (EditableObject selected in selectedObjects)
{
selected.DeselectAll(control);
}
if (hovered != null && !selectedObjects.Contains(hovered))
{
selectedObjects.Clear();
selectedObjects.Add(hovered);
hovered.Select(hoveredPart, control);
SelectionChanged?.Invoke(this, new EventArgs());
}
else
{
selectedObjects.Clear();
SelectionChanged?.Invoke(this, new EventArgs());
}
}
}
else
{
if (selectedObjects.Contains(hovered))
{
selectedObjects.Remove(hovered);
hovered.Deselect(hoveredPart, control);
SelectionChanged?.Invoke(this, new EventArgs());
}
else if(hovered != null)
{
selectedObjects.Add(hovered);
hovered.Select(hoveredPart, control);
SelectionChanged?.Invoke(this, new EventArgs());
}
}
draggingDepth = -1; //because MouseClick implies that the Mouse Button is not pressed anymore
var |= REDRAW;
return var;
}
public override uint MouseWheel(MouseEventArgs e, I3DControl control)
{
uint var = 0;
foreach (EditableObject obj in objects) {
var |= obj.MouseWheel(e, control);
}
foreach (AbstractGlDrawable obj in staticObjects)
{
var |= obj.MouseWheel(e, control);
}
return var;
}
public override int GetPickableSpan()
{
int var = 0;
foreach (EditableObject obj in objects)
var += obj.GetPickableSpan();
foreach (AbstractGlDrawable obj in staticObjects)
var += obj.GetPickableSpan();
return var;
}
public override uint MouseEnter(int index, I3DControl control)
{
int inObjectIndex = index;
if(!(draggingDepth == -1))
return 0;
foreach (EditableObject obj in objects)
{
int span = obj.GetPickableSpan();
Console.WriteLine(obj.ToString() + " span " + span.ToString());
Console.WriteLine(obj.ToString() + " inObjectIndex " + inObjectIndex.ToString());
if (inObjectIndex >= 0 && inObjectIndex < span)
{
hovered = obj;
return obj.MouseEnter(inObjectIndex, control) | REDRAW;
}
inObjectIndex -= span;
}
foreach (AbstractGlDrawable obj in staticObjects)
{
int span = obj.GetPickableSpan();
if (inObjectIndex >= 0 && inObjectIndex < span)
{
return obj.MouseEnter(inObjectIndex, control);
}
inObjectIndex -= span;
}
return 0;
}
public override uint MouseLeave(int index, I3DControl control)
{
int inObjectIndex = index;
foreach (EditableObject obj in objects)
{
int span = obj.GetPickableSpan();
if (inObjectIndex >= 0 && inObjectIndex < span)
{
return obj.MouseLeave(inObjectIndex, control);
}
inObjectIndex -= span;
}
foreach (AbstractGlDrawable obj in staticObjects)
{
int span = obj.GetPickableSpan();
if (inObjectIndex >= 0 && inObjectIndex < span)
{
return obj.MouseLeave(inObjectIndex, control);
}
inObjectIndex -= span;
}
return 0;
}
public override uint MouseLeaveEntirely(I3DControl control)
{
hovered = null;
return REDRAW;
}
public override uint KeyDown(KeyEventArgs e, I3DControl control)
{
uint var = 0;
if(e.KeyCode == Keys.Z && selectedObjects.Count>0)
{
Vector3 sum = new Vector3();
int index = 0;
foreach (EditableObject selected in selectedObjects)
{
sum -= selected.GetSelectionCenter();
index++;
}
sum /= index;
control.CameraTarget = sum;
var = REDRAW_PICKING;
}else if (e.KeyCode == Keys.H && selectedObjects.Count > 0)
{
foreach (EditableObject selected in selectedObjects)
{
selected.Visible = e.Shift;
}
var = REDRAW_PICKING;
}
else if (e.Control && e.KeyCode == Keys.A)
{
if (e.Shift)
{
foreach (EditableObject selected in selectedObjects)
{
selected.DeselectAll(control);
}
selectedObjects.Clear();
SelectionChanged?.Invoke(this, new EventArgs());
}
if (!e.Shift && multiSelect)
{
foreach (EditableObject obj in objects)
{
obj.SelectAll(control);
selectedObjects.Add(obj);
}
SelectionChanged?.Invoke(this, new EventArgs());
}
var = REDRAW;
}
foreach (EditableObject obj in objects) {
var |= obj.KeyDown(e, control);
}
foreach (AbstractGlDrawable obj in staticObjects)
{
var |= obj.KeyDown(e, control);
}
return var;
}
public override uint KeyUp(KeyEventArgs e, I3DControl control)
{
uint var = 0;
foreach (EditableObject obj in objects) {
var |= obj.KeyUp(e, control);
}
foreach (AbstractGlDrawable obj in staticObjects)
{
var |= obj.KeyUp(e, control);
}
return var;
}
public struct SelectInfo
{
public Vector3 LastPos;
public SelectInfo(Vector3 LastPos)
{
this.LastPos = LastPos;
}
}
public struct ObjID : IEquatable<ObjID>
{
public int ObjectIndex;
public int SubObjectIndex;
public static readonly ObjID None = new ObjID(-1, -1);
public bool IsNone()
{
return (ObjectIndex == -1) || (SubObjectIndex == -1);
}
public ObjID(int ObjectIndex, int SubObjectIndex)
{
this.ObjectIndex = ObjectIndex;
this.SubObjectIndex = SubObjectIndex;
}
public bool Equals(ObjID other)
{
return (ObjectIndex == other.ObjectIndex)&&(SubObjectIndex==other.SubObjectIndex);
}
public override int GetHashCode()
{
return (ObjectIndex << 32) + SubObjectIndex;
}
}
public abstract class AbstractTransformAction
{
public abstract Vector3 newPos(Vector3 pos);
public Quaternion deltaRotation;
public Vector3 scale;
public void SetDragDist(Point point) { }
public void SetScrollDragDist(Point point, Point projX, Point projY, Point projZ) { }
}
public class TranslateAction : AbstractTransformAction
{
Vector3 translation = new Vector3();
public override Vector3 newPos(Vector3 pos)
{
return pos + translation;
}
}
}
}

View file

@ -0,0 +1,452 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using GL_EditorFramework.GL_Core;
using GL_EditorFramework.Interfaces;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace GL_EditorFramework.EditorDrawables
{
//this class is under developemnt and won't work right now
/*
public class Path : EditableObject
{
private static bool Initialized = false;
private static ShaderProgram defaultShaderProgram;
private static ShaderProgram defaultLinesShaderProgram;
private static ShaderProgram connectLinesShaderProgram;
private List<PathPoint> pathPoints;
protected Vector4 lineColor = new Vector4(0.75f, 1f, 1f, 1f);
public Path()
{
pathPoints = new List<PathPoint>();
pathPoints.Add(new PathPoint(
new Vector3d(0, 0, 0),
new Vector3d(0, 0, 0),
new Vector3d(3, 0, 0)
));
pathPoints.Add(new PathPoint(
new Vector3d(8, 4, 2),
new Vector3d(-4, 0, 4),
new Vector3d(4, 0, -4)
));
pathPoints.Add(new PathPoint(
new Vector3d(4, 2, -6),
new Vector3d(0, 0, 0),
new Vector3d(0, 0, 0)
));
}
public override void Draw(GL_ControlModern control)
{
GL.LineWidth(2f);
control.CurrentShader = defaultShaderProgram;
Matrix4 mtx = Matrix4.CreateTranslation(Position);
control.UpdateModelMatrix(mtx);
GL.Uniform1(defaultShaderProgram["scale"], 0.5f);
bool picked = EditorScene.IsHovered();
GL.Begin(PrimitiveType.Points);
{
int i = 1;
foreach (PathPoint point in pathPoints)
{
GL.VertexAttrib4(1, (picked || EditorScene.IsHovered(i)) ? CubeColor * 0.5f + hoverColor * 0.5f : CubeColor);
GL.VertexAttrib3(2, point.controlPoint1);
GL.VertexAttrib3(3, point.controlPoint2);
GL.Vertex3(point.position);
i++;
}
}
GL.End();
control.CurrentShader = defaultLinesShaderProgram;
GL.Uniform1(defaultLinesShaderProgram["scale"], 0.5f);
GL.Begin(PrimitiveType.Points);
{
int i = 1;
foreach (PathPoint point in pathPoints)
{
GL.VertexAttrib4(1, (picked || EditorScene.IsHovered(i)) ? hoverColor : lineColor);
GL.VertexAttrib3(2, point.controlPoint1);
GL.VertexAttrib3(3, point.controlPoint2);
GL.Vertex3(point.position);
i++;
}
}
GL.End();
control.CurrentShader = connectLinesShaderProgram;
GL.Uniform4(connectLinesShaderProgram["color"], picked ? hoverColor : CubeColor);
GL.Begin(PrimitiveType.Lines);
for(int i = 1; i<pathPoints.Count; i++)
{
PathPoint p1 = pathPoints[i - 1];
PathPoint p2 = pathPoints[i];
GL.VertexAttrib3(1, p1.controlPoint2);
GL.Vertex3(p1.position);
GL.VertexAttrib3(1, p2.controlPoint1);
GL.Vertex3(p2.position);
}
GL.End();
}
public override void Draw(GL_ControlLegacy control)
{
throw new NotImplementedException();
}
public override void DrawPicking(GL_ControlModern control)
{
control.CurrentShader = connectLinesShaderProgram;
Matrix4 mtx = Matrix4.CreateTranslation(Position);
control.UpdateModelMatrix(mtx);
GL.Uniform4(connectLinesShaderProgram["color"], control.nextPickingColor());
GL.Begin(PrimitiveType.Lines);
for (int i = 1; i < pathPoints.Count; i++)
{
PathPoint p1 = pathPoints[i - 1];
PathPoint p2 = pathPoints[i];
GL.VertexAttrib3(1, p1.controlPoint2);
GL.Vertex3(p1.position);
GL.VertexAttrib3(1, p2.controlPoint1);
GL.Vertex3(p2.position);
}
GL.End();
control.CurrentShader = defaultShaderProgram;
GL.Uniform1(defaultShaderProgram["scale"], 0.5f);
GL.Begin(PrimitiveType.Points);
foreach (PathPoint point in pathPoints)
{
System.Drawing.Color c = control.nextPickingColor();
GL.VertexAttrib4(1, c.R/256f, c.G / 256f, c.B / 256f, c.A / 256f);
GL.VertexAttrib3(2, point.controlPoint1);
GL.VertexAttrib3(3, point.controlPoint2);
GL.Vertex3(point.position);
}
GL.End();
}
public override void Prepare(GL_ControlModern control)
{
if (!Initialized)
{
var defaultFrag = new FragmentShader(
@"#version 330
in vec4 fragColor;
void main(){
gl_FragColor = fragColor;
}");
var defaultVert = new VertexShader(
@"#version 330
in vec4 position;
layout(location = 1) in vec4 color;
layout(location = 2) in vec3 _cp1;
layout(location = 3) in vec3 _cp2;
out vec4 vertColor;
out vec4 cp1;
out vec4 cp2;
void main(){
cp1 = vec4(_cp1,0);
cp2 = vec4(_cp2,0);
vertColor = color;
gl_Position = position;
}");
#region block shader
defaultShaderProgram = new ShaderProgram(defaultFrag, defaultVert);
defaultShaderProgram.AttachShader(new Shader(
@"#version 330
layout(points) in;
layout(triangle_strip, max_vertices = 72) out;
in vec4 vertColor[];
in vec4 cp1[];
in vec4 cp2[];
out vec4 fragColor;
uniform mat4 mtxMdl;
uniform mat4 mtxCam;
uniform float scale;
float cubeScale;
vec4 pos;
mat4 mtx = mtxCam*mtxMdl;
vec4 points[8] = vec4[](
vec4(-1.0,-1.0,-1.0, 0.0),
vec4( 1.0,-1.0,-1.0, 0.0),
vec4(-1.0, 1.0,-1.0, 0.0),
vec4( 1.0, 1.0,-1.0, 0.0),
vec4(-1.0,-1.0, 1.0, 0.0),
vec4( 1.0,-1.0, 1.0, 0.0),
vec4(-1.0, 1.0, 1.0, 0.0),
vec4( 1.0, 1.0, 1.0, 0.0)
);
void face(int p1, int p2, int p3, int p4){
gl_Position = mtx * (pos + points[p1]*cubeScale); EmitVertex();
gl_Position = mtx * (pos + points[p2]*cubeScale); EmitVertex();
gl_Position = mtx * (pos + points[p3]*cubeScale); EmitVertex();
gl_Position = mtx * (pos + points[p4]*cubeScale); EmitVertex();
EndPrimitive();
}
void faceInv(int p3, int p4, int p1, int p2){
gl_Position = mtx * (pos + points[p1]*cubeScale); EmitVertex();
gl_Position = mtx * (pos + points[p2]*cubeScale); EmitVertex();
gl_Position = mtx * (pos + points[p3]*cubeScale); EmitVertex();
gl_Position = mtx * (pos + points[p4]*cubeScale); EmitVertex();
EndPrimitive();
}
void main(){
cubeScale = scale;
pos = gl_in[0].gl_Position;
fragColor = vertColor[0];
face(0,1,2,3);
faceInv(4,5,6,7);
faceInv(0,1,4,5);
face(2,3,6,7);
face(0,2,4,6);
faceInv(1,3,5,7);
cubeScale = scale*0.5;
if(cp1[0]!=vec4(0,0,0,0)){
pos = gl_in[0].gl_Position+cp1[0];
face(0,1,2,3);
faceInv(4,5,6,7);
faceInv(0,1,4,5);
face(2,3,6,7);
face(0,2,4,6);
faceInv(1,3,5,7);
}
if(cp2[0]!=vec4(0,0,0,0)){
pos = gl_in[0].gl_Position+cp2[0];
face(0,1,2,3);
faceInv(4,5,6,7);
faceInv(0,1,4,5);
face(2,3,6,7);
face(0,2,4,6);
faceInv(1,3,5,7);
}
}
", ShaderType.GeometryShader));
defaultShaderProgram.LinkShaders();
#endregion
#region lines shader
defaultLinesShaderProgram = new ShaderProgram(defaultFrag, defaultVert);
defaultLinesShaderProgram.AttachShader(new Shader(
@"#version 330
layout(points) in;
layout(line_strip, max_vertices = 72) out;
in vec4 vertColor[];
in vec4 cp1[];
in vec4 cp2[];
out vec4 fragColor;
uniform mat4 mtxMdl;
uniform mat4 mtxCam;
uniform float scale;
float cubeScale;
vec4 pos;
mat4 mtx = mtxCam*mtxMdl;
vec4 points[8] = vec4[](
vec4(-1.0,-1.0,-1.0, 0.0),
vec4( 1.0,-1.0,-1.0, 0.0),
vec4(-1.0, 1.0,-1.0, 0.0),
vec4( 1.0, 1.0,-1.0, 0.0),
vec4(-1.0,-1.0, 1.0, 0.0),
vec4( 1.0,-1.0, 1.0, 0.0),
vec4(-1.0, 1.0, 1.0, 0.0),
vec4( 1.0, 1.0, 1.0, 0.0)
);
void face(int p1, int p2, int p4, int p3){
gl_Position = mtx * (pos + points[p1]*cubeScale); EmitVertex();
gl_Position = mtx * (pos + points[p2]*cubeScale); EmitVertex();
gl_Position = mtx * (pos + points[p3]*cubeScale); EmitVertex();
gl_Position = mtx * (pos + points[p4]*cubeScale); EmitVertex();
gl_Position = mtx * (pos + points[p1]*cubeScale); EmitVertex();
EndPrimitive();
}
void line(int p1, int p2){
gl_Position = mtx * (pos + points[p1]*cubeScale); EmitVertex();
gl_Position = mtx * (pos + points[p2]*cubeScale); EmitVertex();
EndPrimitive();
}
void main(){
cubeScale = scale;
pos = gl_in[0].gl_Position;
fragColor = vertColor[0];
face(0,1,2,3);
face(4,5,6,7);
line(0,4);
line(1,5);
line(2,6);
line(3,7);
cubeScale = scale*0.5;
if(cp1[0]!=vec4(0,0,0,0)){
pos = gl_in[0].gl_Position+cp1[0];
face(0,1,2,3);
face(4,5,6,7);
line(0,4);
line(1,5);
line(2,6);
line(3,7);
}
if(cp2[0]!=vec4(0,0,0,0)){
pos = gl_in[0].gl_Position+cp2[0];
face(0,1,2,3);
face(4,5,6,7);
line(0,4);
line(1,5);
line(2,6);
line(3,7);
}
}
", ShaderType.GeometryShader));
defaultLinesShaderProgram.LinkShaders();
#endregion
var connectLinesFrag = new FragmentShader(
@"#version 330
uniform vec4 color;
void main(){
gl_FragColor = color;
}");
var connectLinesVert = new VertexShader(
@"#version 330
in vec4 position;
layout(location = 1) in vec3 _controlPoint;
out vec4 controlPoint;
void main(){
controlPoint = vec4(_controlPoint,0.0);
gl_Position = position;
}");
#region connections shader
connectLinesShaderProgram = new ShaderProgram(connectLinesFrag, connectLinesVert);
connectLinesShaderProgram.AttachShader(new Shader(
@"#version 330
layout(lines) in;
layout(line_strip, max_vertices = 19) out;
in vec4 controlPoint[];
uniform mat4 mtxMdl;
uniform mat4 mtxCam;
mat4 mtx = mtxCam*mtxMdl;
vec4 p0 = gl_in[0].gl_Position;
vec4 p1 = gl_in[0].gl_Position + controlPoint[0];
vec4 p2 = gl_in[1].gl_Position + controlPoint[1];
vec4 p3 = gl_in[1].gl_Position;
void getPointAtTime(float t){
float u = 1f - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;
gl_Position = mtx * (uuu * p0 +
3 * uu * t * p1 +
3 * u *tt * p2 +
ttt * p3);
EmitVertex();
}
void main(){
gl_Position = mtx * p1;
EmitVertex();
for(float t = 0; t<=1.0; t+=0.0625){
getPointAtTime(t);
}
gl_Position = mtx * p2;
EmitVertex();
EndPrimitive();
}
", ShaderType.GeometryShader));
#endregion
connectLinesShaderProgram.LinkShaders();
Initialized = true;
}
}
public override void Prepare(GL_ControlLegacy control)
{
throw new NotImplementedException();
}
public override int GetPickableSpan() => pathPoints.Count + 1;
struct PathPoint
{
public PathPoint(Vector3d position, Vector3d controlPoint1, Vector3d controlPoint2)
{
this.position = position;
this.controlPoint1 = controlPoint1;
this.controlPoint2 = controlPoint2;
}
public Vector3d position;
public Vector3d controlPoint1;
public Vector3d controlPoint2;
}
}
*/
}

View file

@ -0,0 +1,183 @@
using GL_EditorFramework.GL_Core;
using GL_EditorFramework.Interfaces;
using OpenGl_EditorFramework;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GL_EditorFramework.EditorDrawables
{
//
// Summary:
// An EditableObject that has only one selectable Part. It's represented by a blue block
public class SingleObject : EditableObject
{
public Vector3 Position = new Vector3(0, 0, 0);
protected bool Selected = false;
public override bool IsSelected() => Selected;
protected static Vector4 Color = new Vector4(0f, 0.25f, 1f, 1f);
public SingleObject(Vector3 pos)
{
Position = pos;
}
public override void Draw(GL_ControlModern control, Pass pass, EditorScene editorScene)
{
if (pass == Pass.TRANSPARENT)
return;
bool hovered = editorScene.hovered == this;
control.UpdateModelMatrix(Matrix4.CreateScale(0.5f) *
Matrix4.CreateTranslation(Position + (Selected ? editorScene.deltaTransform.Translation : new Vector3())));
Vector4 blockColor;
Vector4 lineColor;
if (hovered && Selected)
lineColor = hoverColor;
else if (hovered || Selected)
lineColor = selectColor;
else
lineColor = Color;
if (hovered && Selected)
blockColor = Color * 0.5f + hoverColor * 0.5f;
else if (hovered || Selected)
blockColor = Color * 0.5f + selectColor * 0.5f;
else
blockColor = Color;
Renderers.ColorBlockRenderer.Draw(control, pass, blockColor, lineColor, control.nextPickingColor());
}
public override void Draw(GL_ControlModern control, Pass pass)
{
if (pass == Pass.TRANSPARENT)
return;
control.UpdateModelMatrix(Matrix4.CreateScale(0.5f) *
Matrix4.CreateTranslation(Position));
Renderers.ColorBlockRenderer.Draw(control, pass, Color, Color, control.nextPickingColor());
}
public override void Draw(GL_ControlLegacy control, Pass pass, EditorScene editorScene)
{
if (pass == Pass.TRANSPARENT)
return;
bool hovered = editorScene.hovered == this;
control.UpdateModelMatrix(Matrix4.CreateScale(0.5f) *
Matrix4.CreateTranslation(Position + (Selected ? editorScene.deltaTransform.Translation : new Vector3())));
Vector4 blockColor;
Vector4 lineColor;
if (hovered && Selected)
lineColor = hoverColor;
else if (hovered || Selected)
lineColor = selectColor;
else
lineColor = Color;
if (hovered && Selected)
blockColor = Color * 0.5f + hoverColor * 0.5f;
else if (hovered || Selected)
blockColor = Color * 0.5f + selectColor * 0.5f;
else
blockColor = Color;
Renderers.ColorBlockRenderer.Draw(control, pass, blockColor, lineColor, control.nextPickingColor());
}
public override void Draw(GL_ControlLegacy control, Pass pass)
{
if (pass == Pass.TRANSPARENT)
return;
control.UpdateModelMatrix(Matrix4.CreateScale(0.5f) *
Matrix4.CreateTranslation(Position));
Renderers.ColorBlockRenderer.Draw(control, pass, Color, Color, control.nextPickingColor());
}
public override void Prepare(GL_ControlModern control)
{
Renderers.ColorBlockRenderer.Initialize();
}
public override void Prepare(GL_ControlLegacy control)
{
}
public virtual void Translate(Vector3 lastPos, Vector3 translate, int subObj)
{
Position = lastPos + translate;
}
public virtual void UpdatePosition(int subObj)
{
}
public override bool CanStartDragging() => true;
public override Vector3 GetSelectionCenter()
{
return Position;
}
public override uint SelectAll(I3DControl control)
{
Selected = true;
return REDRAW;
}
public override uint SelectDefault(I3DControl control)
{
Selected = true;
return REDRAW;
}
public override uint Select(int partIndex, I3DControl control)
{
Selected = true;
return REDRAW;
}
public override uint Deselect(int partIndex, I3DControl control)
{
Selected = false;
return REDRAW;
}
public override uint DeselectAll(I3DControl control)
{
Selected = false;
return REDRAW;
}
public override void ApplyTransformationToSelection(DeltaTransform deltaTransform)
{
Position += deltaTransform.Translation;
}
}
}

View file

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GL_EditorFramework.GL_Core;
using OpenTK.Graphics.OpenGL;
namespace GL_EditorFramework
{
public sealed class Framework {
public static void Initialize()
{
if (initialized)
return;
//texture sheet
TextureSheet = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, TextureSheet);
var bmp = OpenGl_EditorFramework.Properties.Resources.TextureSheet;
var bmpData = bmp.LockBits(
new System.Drawing.Rectangle(0, 0, 128*4, 128*2),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, 128*4, 128*2, 0, PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
bmp.UnlockBits(bmpData);
initialized = true;
}
private static bool initialized = false;
public static int TextureSheet;
}
}

View file

@ -0,0 +1,78 @@
using GL_EditorFramework.Interfaces;
using OpenTK;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GL_EditorFramework.StandardCameras
{
public class InspectCamera : AbstractCamera
{
private float maxCamMoveSpeed;
public InspectCamera(float maxCamMoveSpeed = 0.1f)
{
this.maxCamMoveSpeed = maxCamMoveSpeed;
}
public override uint MouseDown(MouseEventArgs e, I3DControl control)
{
if (OpenTK.Input.Keyboard.GetState().IsKeyDown(OpenTK.Input.Key.ControlLeft) &&
e.Button == MouseButtons.Right &&
control.PickingDepth != control.ZFar)
{
control.CameraTarget = control.coordFor(e.X, e.Y, control.PickingDepth);
return UPDATE_CAMERA;
}
return base.MouseDown(e, control);
}
public override uint MouseMove(MouseEventArgs e, Point lastMouseLoc, I3DControl control)
{
float deltaX = e.Location.X - lastMouseLoc.X;
float deltaY = e.Location.Y - lastMouseLoc.Y;
if (e.Button == MouseButtons.Right)
{
control.CamRotX += deltaX * 0.002f;
control.CamRotY += deltaY * 0.002f;
return UPDATE_CAMERA;
}
else if (e.Button == MouseButtons.Left)
{
base.MouseMove(e, lastMouseLoc, control);
if (OpenTK.Input.Keyboard.GetState().IsKeyDown(OpenTK.Input.Key.ControlLeft))
control.CameraDistance *= 1f - deltaY*-5 * 0.001f;
else
{
//code from Whitehole
deltaX *= Math.Min(maxCamMoveSpeed, depth * control.FactorX);
deltaY *= Math.Min(maxCamMoveSpeed, depth * control.FactorY);
control.CameraTarget += Vector3.UnitX * deltaX * (float)Math.Cos(control.CamRotX);
control.CameraTarget -= Vector3.UnitX * deltaY * (float)Math.Sin(control.CamRotX) * (float)Math.Sin(control.CamRotY);
control.CameraTarget -= Vector3.UnitY * deltaY * (float)Math.Cos(control.CamRotY);
control.CameraTarget += Vector3.UnitZ * deltaX * (float)Math.Sin(control.CamRotX);
control.CameraTarget += Vector3.UnitZ * deltaY * (float)Math.Cos(control.CamRotX) * (float)Math.Sin(control.CamRotY);
}
return UPDATE_CAMERA;
}
return 0;
}
public override uint MouseWheel(MouseEventArgs e, I3DControl control)
{
control.CameraDistance *= 1f - e.Delta * 0.001f;
return UPDATE_CAMERA;
}
}
}

View file

@ -0,0 +1,112 @@
using GL_EditorFramework.Interfaces;
using OpenTK;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GL_EditorFramework.StandardCameras
{
public class WalkaroundCamera : AbstractCamera
{
private float maxCamMoveSpeed;
public WalkaroundCamera(float maxCamMoveSpeed = 0.1f)
{
this.maxCamMoveSpeed = maxCamMoveSpeed;
}
public override uint MouseDown(MouseEventArgs e, I3DControl control)
{
if (OpenTK.Input.Keyboard.GetState().IsKeyDown(OpenTK.Input.Key.ControlLeft) &&
e.Button == MouseButtons.Right &&
control.PickingDepth != control.ZFar)
{
float delta = control.PickingDepth + control.CameraDistance;
control.CameraTarget -= Vector3.UnitX * (float)Math.Sin(control.CamRotX) * (float)Math.Cos(control.CamRotY) * delta;
control.CameraTarget += Vector3.UnitY * (float)Math.Sin(control.CamRotY) * delta;
control.CameraTarget += Vector3.UnitZ * (float)Math.Cos(control.CamRotX) * (float)Math.Cos(control.CamRotY) * delta;
Vector2 normCoords = control.NormMouseCoords(e.Location.X, e.Location.Y);
float factoffX = (float)(-normCoords.X * control.PickingDepth) * control.FactorX;
float factoffY = (float)(-normCoords.Y * control.PickingDepth) * control.FactorY;
control.CameraTarget += Vector3.UnitX * (float)Math.Cos(control.CamRotX) * factoffX;
control.CameraTarget -= Vector3.UnitX * (float)Math.Sin(control.CamRotX) * (float)Math.Sin(control.CamRotY) * factoffY;
control.CameraTarget -= Vector3.UnitY * (float)Math.Cos(control.CamRotY) * factoffY;
control.CameraTarget += Vector3.UnitZ * (float)Math.Sin(control.CamRotX) * factoffX;
control.CameraTarget += Vector3.UnitZ * (float)Math.Cos(control.CamRotX) * (float)Math.Sin(control.CamRotY) * factoffY;
}
base.MouseDown(e, control);
return UPDATE_CAMERA;
}
public override uint MouseMove(MouseEventArgs e, Point lastMouseLoc, I3DControl control)
{
float deltaX = e.Location.X - lastMouseLoc.X;
float deltaY = e.Location.Y - lastMouseLoc.Y;
if (e.Button == MouseButtons.Right)
{
control.CamRotX += deltaX * 0.00390625f;
control.CamRotY += deltaY * 0.00390625f;
return UPDATE_CAMERA;
}
else if (e.Button == MouseButtons.Left)
{
base.MouseMove(e, lastMouseLoc, control);
if (OpenTK.Input.Keyboard.GetState().IsKeyDown(OpenTK.Input.Key.ControlLeft))
{
float delta = ((float)deltaY*-5 * Math.Min(0.01f, depth / 500f));
control.CameraTarget -= Vector3.UnitX * (float)Math.Sin(control.CamRotX) * (float)Math.Cos(control.CamRotY) * delta;
control.CameraTarget += Vector3.UnitY * (float)Math.Sin(control.CamRotY) * delta;
control.CameraTarget += Vector3.UnitZ * (float)Math.Cos(control.CamRotX) * (float)Math.Cos(control.CamRotY) * delta;
}
else
{
//code from Whitehole
deltaX *= Math.Min(maxCamMoveSpeed, depth * control.FactorX);
deltaY *= Math.Min(maxCamMoveSpeed, depth * control.FactorY);
control.CameraTarget += Vector3.UnitX * deltaX * (float)Math.Cos(control.CamRotX);
control.CameraTarget -= Vector3.UnitX * deltaY * (float)Math.Sin(control.CamRotX) * (float)Math.Sin(control.CamRotY);
control.CameraTarget -= Vector3.UnitY * deltaY * (float)Math.Cos(control.CamRotY);
control.CameraTarget += Vector3.UnitZ * deltaX * (float)Math.Sin(control.CamRotX);
control.CameraTarget += Vector3.UnitZ * deltaY * (float)Math.Cos(control.CamRotX) * (float)Math.Sin(control.CamRotY);
}
return UPDATE_CAMERA;
}
return 0;
}
public override uint MouseWheel(MouseEventArgs e, I3DControl control)
{
depth = control.PickingDepth;
float delta = ((float)e.Delta * Math.Min(0.01f, depth / 500f));
control.CameraTarget -= Vector3.UnitX * (float)Math.Sin(control.CamRotX) * (float)Math.Cos(control.CamRotY) * delta;
control.CameraTarget += Vector3.UnitY * (float)Math.Sin(control.CamRotY) * delta;
control.CameraTarget += Vector3.UnitZ * (float)Math.Cos(control.CamRotX) * (float)Math.Cos(control.CamRotY) * delta;
Vector2 normCoords = control.NormMouseCoords(e.Location.X, e.Location.Y);
float factoffX = (float)(-normCoords.X * delta) * control.FactorX;
float factoffY = (float)(-normCoords.Y * delta) * control.FactorY;
control.CameraTarget += Vector3.UnitX * (float)Math.Cos(control.CamRotX) * factoffX;
control.CameraTarget -= Vector3.UnitX * (float)Math.Sin(control.CamRotX) * (float)Math.Sin(control.CamRotY) * factoffY;
control.CameraTarget -= Vector3.UnitY * (float)Math.Cos(control.CamRotY) * factoffY;
control.CameraTarget += Vector3.UnitZ * (float)Math.Sin(control.CamRotX) * factoffX;
control.CameraTarget += Vector3.UnitZ * (float)Math.Cos(control.CamRotX) * (float)Math.Sin(control.CamRotY) * factoffY;
return UPDATE_CAMERA;
}
}
}

View file

@ -0,0 +1,673 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using GL_EditorFramework.Interfaces;
using GL_EditorFramework.StandardCameras;
using System.Drawing;
using System.Windows.Forms;
namespace GL_EditorFramework.GL_Core
{
public class GL_ControlBase : GLControl, I3DControl
{
public GL_ControlBase(int maxGL_Version, int redrawerInterval) : base(OpenTK.Graphics.GraphicsMode.Default, maxGL_Version, 1, OpenTK.Graphics.GraphicsContextFlags.Default)
{
redrawer.Interval = redrawerInterval;
redrawer.Tick += Redrawer_Tick;
}
private void Redrawer_Tick(object sender, EventArgs e)
{
base.Refresh();
if (repickerOwners > 0)
Repick();
RedrawerFrame++;
}
public GL_ControlBase() : base(OpenTK.Graphics.GraphicsMode.Default, 1, 1, OpenTK.Graphics.GraphicsContextFlags.Default)
{
}
protected Matrix4 orientationCubeMtx;
protected bool showFakeCursor;
private Timer redrawer = new Timer();
private uint redrawerOwners = 0;
private uint repickerOwners = 0;
protected Point lastMouseLoc;
protected Point dragStartPos = new Point(-1, -1);
protected float camRotX = 0;
protected float camRotY = 0;
protected float camDistance = -10f;
protected Vector3 camTarget;
protected float zfar = 1000f;
protected float znear = 0.01f;
protected float fov = MathHelper.PiOver4;
public float PickedObjectPart => pickingFrameBuffer;
protected uint pickingFrameBuffer;
protected int pickingIndex;
private int lastPicked = -1;
protected float normPickingDepth = 0f;
protected float pickingDepth = 0f;
public Matrix4 mtxMdl, mtxCam, mtxProj;
protected float factorX, factorY;
protected bool stereoscopy;
protected bool showOrientationCube = true;
protected int viewPortX(int x) => stereoscopy ? x % (Width / 2) : x;
protected int viewPortDX(int dx) => stereoscopy ? dx * 2 : dx;
protected int viewPortXOff(int x) => stereoscopy ? (x - Width / 4) * 2 : x - Width / 2;
public Color BackgroundColor1 = Color.FromArgb(20, 20, 20);
public Color BackgroundColor2 = Color.FromArgb(70, 70, 70);
public bool GradientBackground;
public Point DragStartPos
{
get => dragStartPos;
set
{
dragStartPos = value;
}
}
public bool Stereoscopy
{
get => stereoscopy;
set
{
stereoscopy = value;
OnResize(null);
Refresh();
}
}
public bool ShowOrientationCube
{
get => showOrientationCube;
set
{
showOrientationCube = value;
pickingIndexOffset = value?7:1;
Refresh();
}
}
public Vector3 coordFor(int x, int y, float depth)
{
Vector3 vec = camTarget;
float delta = depth + camDistance;
vec -= Vector3.UnitX * (float)Math.Sin(camRotX) * (float)Math.Cos(camRotY) * delta;
vec += Vector3.UnitY * (float)Math.Sin(camRotY) * delta;
vec += Vector3.UnitZ * (float)Math.Cos(camRotX) * (float)Math.Cos(camRotY) * delta;
Vector2 normCoords = NormMouseCoords(x, y);
float factoffX = (float)(-normCoords.X * depth) * factorX;
float factoffY = (float)(-normCoords.Y * depth) * factorY;
vec += Vector3.UnitX * (float)Math.Cos(camRotX) * factoffX;
vec -= Vector3.UnitX * (float)Math.Sin(camRotX) * (float)Math.Sin(camRotY) * factoffY;
vec -= Vector3.UnitY * (float)Math.Cos(camRotY) * factoffY;
vec += Vector3.UnitZ * (float)Math.Sin(camRotX) * factoffX;
vec += Vector3.UnitZ * (float)Math.Cos(camRotX) * (float)Math.Sin(camRotY) * factoffY;
return vec;
//TODO: Get this working, to get rid of sin and cos functions
/*
Vector4 vec;
vec.X = 2.0f * x / (float)Width - 1;
vec.Y = -(2.0f * y / (float)Height) + 1;
vec.Z = normDepth;
vec.W = 1.0f;
Matrix4 viewInv = Matrix4.Invert(mtxCam);
Matrix4 projInv = Matrix4.Invert(mtxProj);
Vector4.Transform(ref vec, ref projInv, out vec);
Vector4.Transform(ref vec, ref viewInv, out vec);
if (vec.W > 0.000001f || vec.W < -0.000001f)
{
vec.X /= vec.W;
vec.Y /= vec.W;
vec.Z /= vec.W;
}
vec.X *= -1;
vec.Y *= -1;
vec.Z *= -1;
return vec.Xyz;
*/
}
public Vector3 screenCoordFor(Vector3 coord)
{
return new Vector3();
}
protected AbstractGlDrawable mainDrawable;
public virtual AbstractGlDrawable MainDrawable { get; set; }
protected AbstractCamera activeCamera;
private bool shouldRedraw;
private bool shouldRepick;
private bool skipCameraAction;
private int pickingIndexOffset = 7;
public AbstractCamera ActiveCamera
{
get => activeCamera;
set
{
if (value == null) return;
activeCamera = value;
MakeCurrent();
Refresh();
}
}
public int ViewWidth => stereoscopy ? Width / 2 : Width;
public int ViewHeighth => Height;
public Vector2 NormMouseCoords(int x, int y) {
return new Vector2(x - Width / 2, y - Height / 2);
}
public float ZFar { get => zfar; set { zfar = value; } }
public float ZNear { get => znear; set { znear = value; } }
public float Fov { get => fov; set { fov = value; } }
public float FactorX => factorX;
public float FactorY => factorY;
public Vector3 CameraTarget { get => camTarget; set { camTarget = value; } }
public float CameraDistance { get => camDistance; set { camDistance = value; } }
public float CamRotX { get => camRotX; set { camRotX = value; } }
public float CamRotY { get => camRotY; set { camRotY = value; } }
public float PickingDepth => pickingDepth;
public float NormPickingDepth => normPickingDepth;
public ulong RedrawerFrame { get; private set; } = 0;
void handleDrawableEvtResult(uint result)
{
shouldRedraw |= (result&AbstractGlDrawable.REDRAW)> 0;
shouldRepick |= (result & AbstractGlDrawable.REPICK) > 0;
skipCameraAction |= (result & AbstractGlDrawable.NO_CAMERA_ACTION) > 0;
}
void handleCameraEvtResult(uint result)
{
shouldRedraw |= result > 0;
shouldRepick |= result > 0;
}
public Color nextPickingColor()
{
return Color.FromArgb(pickingIndex++);
}
public void skipPickingColors(uint count)
{
pickingIndex += (int)count;
}
public virtual void UpdateModelMatrix(Matrix4 matrix) { }
public virtual void ApplyModelTransform(Matrix4 matrix) { }
public virtual void ResetModelMatrix() { }
protected override void OnLoad(EventArgs e)
{
if (DesignMode) return;
activeCamera = new WalkaroundCamera();
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.CullFace);
GL.CullFace(CullFaceMode.Back);
GL.Enable(EnableCap.Texture2D);
GL.Enable(EnableCap.AlphaTest);
GL.Enable(EnableCap.LineSmooth);
GL.Enable(EnableCap.PolygonSmooth);
}
protected override void OnResize(EventArgs e)
{
if (DesignMode) return;
float aspect_ratio;
if (stereoscopy)
aspect_ratio = Width / 2 / (float)Height;
else
aspect_ratio = Width / (float)Height;
mtxProj = Matrix4.CreatePerspectiveFieldOfView(fov, aspect_ratio, znear, zfar);
//using the calculation from whitehole
factorX = (2f * (float)Math.Tan(fov * 0.5f) * aspect_ratio) / Width;
factorY = (2f * (float)Math.Tan(fov * 0.5f)) / Height;
Refresh();
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (DesignMode || mainDrawable == null) return;
Focus();
lastMouseLoc = e.Location;
if(dragStartPos == new Point(-1,-1))
dragStartPos = e.Location;
shouldRedraw = false;
shouldRepick = false;
skipCameraAction = false;
handleDrawableEvtResult(mainDrawable.MouseDown(e, this));
if (!skipCameraAction)
handleCameraEvtResult(activeCamera.MouseDown(e, this));
if (shouldRepick)
Repick();
if (shouldRedraw)
Refresh();
base.OnMouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (DesignMode || mainDrawable == null) return;
shouldRedraw = false;
shouldRepick = false;
skipCameraAction = false;
handleDrawableEvtResult(mainDrawable.MouseMove(e, lastMouseLoc, this));
if (!skipCameraAction)
{
handleCameraEvtResult(activeCamera.MouseMove(e, lastMouseLoc, this));
}
if (shouldRepick)
Repick();
if (shouldRedraw||showFakeCursor)
Refresh();
lastMouseLoc = e.Location;
}
protected override void OnMouseWheel(MouseEventArgs e)
{
if (DesignMode || mainDrawable == null) return;
shouldRedraw = false;
shouldRepick = false;
skipCameraAction = false;
handleDrawableEvtResult(mainDrawable.MouseWheel(e, this));
if (!skipCameraAction)
handleCameraEvtResult(activeCamera.MouseWheel(e, this));
if (shouldRepick)
Repick();
if (shouldRedraw)
Refresh();
}
protected override void OnMouseUp(MouseEventArgs e)
{
if (DesignMode || mainDrawable == null) return;
shouldRedraw = false;
shouldRepick = false;
skipCameraAction = false;
if((e.Location.X == dragStartPos.X) && (e.Location.Y == dragStartPos.Y))
{
shouldRedraw = true;
switch (showOrientationCube ? pickingFrameBuffer : 0)
{
case 1:
camRotX = 0;
camRotY = (float)Math.PI * 0.5f;
break;
case 2:
camRotX = 0;
camRotY = -(float)Math.PI * 0.5f;
break;
case 3:
camRotX = 0;
camRotY = 0;
break;
case 4:
camRotX = (float)Math.PI;
camRotY = 0;
break;
case 5:
camRotX = -(float)Math.PI * 0.5f;
camRotY = 0;
break;
case 6:
camRotX = (float)Math.PI * 0.5f;
camRotY = 0;
break;
default:
shouldRedraw = false;
handleDrawableEvtResult(mainDrawable.MouseClick(e, this));
break;
}
}
else
{
handleDrawableEvtResult(mainDrawable.MouseUp(e, this));
}
dragStartPos = new Point(-1, -1);
if (!skipCameraAction)
handleCameraEvtResult(activeCamera.MouseUp(e, this));
if (shouldRepick)
Repick();
if (shouldRedraw)
Refresh();
}
protected void Repick()
{
int pickingMouseX = stereoscopy ? lastMouseLoc.X / 2 : lastMouseLoc.X;
pickingIndex = 1;
DrawPicking();
GL.Flush();
GL.ReadPixels(pickingMouseX, Height - lastMouseLoc.Y, 1, 1, PixelFormat.Bgra, PixelType.UnsignedByte, ref pickingFrameBuffer);
// depth math from http://www.opengl.org/resources/faq/technical/depthbuffer.htm
GL.ReadPixels(pickingMouseX, Height - lastMouseLoc.Y, 1, 1, PixelFormat.DepthComponent, PixelType.Float, ref normPickingDepth);
pickingDepth = -(zfar * znear / (normPickingDepth * (zfar - znear) - zfar));
Console.WriteLine(normPickingDepth);
int picked = (int)pickingFrameBuffer - pickingIndexOffset;
if (lastPicked != picked)
{
if (picked >= 0)
{
handleDrawableEvtResult(mainDrawable.MouseEnter(picked, this));
}
else
{
handleDrawableEvtResult(mainDrawable.MouseLeaveEntirely(this));
}
if (lastPicked >= 0)
{
handleDrawableEvtResult(mainDrawable.MouseLeave(lastPicked, this));
}
lastPicked = picked;
}
}
protected override void OnMouseEnter(EventArgs e)
{
if (DesignMode)
{
base.OnMouseEnter(e);
return;
}
if (stereoscopy)
{
showFakeCursor = true;
Cursor.Hide();
}
base.OnMouseEnter(e);
}
protected override void OnMouseLeave(EventArgs e)
{
if (DesignMode)
{
base.OnMouseLeave(e);
return;
}
if (stereoscopy)
{
showFakeCursor = false;
Cursor.Show();
}
base.OnMouseLeave(e);
Refresh();
}
protected override void OnKeyDown(KeyEventArgs e)
{
if (DesignMode || mainDrawable == null) return;
shouldRedraw = false;
shouldRepick = false;
skipCameraAction = false;
handleDrawableEvtResult(mainDrawable.KeyDown(e, this));
if (!skipCameraAction)
handleCameraEvtResult(activeCamera.KeyDown(e, this));
if (shouldRepick)
Repick();
if (shouldRedraw)
Refresh();
}
protected override void OnKeyUp(KeyEventArgs e)
{
if (DesignMode || mainDrawable == null) return;
shouldRedraw = false;
shouldRepick = false;
skipCameraAction = false;
handleDrawableEvtResult(mainDrawable.KeyUp(e, this));
if (skipCameraAction)
handleCameraEvtResult(activeCamera.KeyUp(e, this));
if (shouldRepick)
Repick();
if (shouldRedraw)
Refresh();
}
public virtual void DrawPicking() { }
protected void DrawFakeCursor()
{
GL.Color3(1f, 1f, 1f);
GL.Disable(EnableCap.Texture2D);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
GL.Translate(lastMouseLoc.X * 2 / (float)Width - 1, -(lastMouseLoc.Y * 2 / (float)Height - 1), 0);
GL.Scale(80f / Width, 40f / Height, 1);
GL.Begin(PrimitiveType.Polygon);
GL.Vertex2(0, 0);
GL.Vertex2(0, -1);
GL.Vertex2(0.25, -0.75);
GL.Vertex2(0.625, -0.75);
GL.End();
GL.Enable(EnableCap.Texture2D);
}
protected void DrawOrientationCube()
{
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, Framework.TextureSheet);
GL.Disable(EnableCap.DepthTest);
GL.Begin(PrimitiveType.Quads);
GL.Color3(new Vector3(pickingFrameBuffer == 1 ? 1f : 0.75f)); //UP
GL.TexCoord2(0f, 1f);
GL.Vertex3(-1f, 1f, 1f);
GL.TexCoord2(0.25f, 1f);
GL.Vertex3(1f, 1f, 1f);
GL.TexCoord2(0.25f, 0.5f);
GL.Vertex3(1f, 1f, -1f);
GL.TexCoord2(0f, 0.5f);
GL.Vertex3(-1f, 1f, -1f);
GL.Color3(new Vector3(pickingFrameBuffer == 2 ? 1f : 0.75f)); //DOWN
GL.TexCoord2(0.25f, 1f);
GL.Vertex3(-1f, -1f, -1f);
GL.TexCoord2(0.5f, 1f);
GL.Vertex3(1f, -1f, -1f);
GL.TexCoord2(0.5f, 0.5f);
GL.Vertex3(1f, -1f, 1f);
GL.TexCoord2(0.25f, 0.5f);
GL.Vertex3(-1f, -1f, 1f);
GL.Color3(new Vector3(pickingFrameBuffer == 3 ? 1f : 0.75f)); //FRONT
GL.TexCoord2(0.25f, 0f);
GL.Vertex3(1f, 1f, 1f);
GL.TexCoord2(0f, 0f);
GL.Vertex3(-1f, 1f, 1f);
GL.TexCoord2(0f, 0.5f);
GL.Vertex3(-1f, -1f, 1f);
GL.TexCoord2(0.25f, 0.5f);
GL.Vertex3(1f, -1f, 1f);
GL.Color3(new Vector3(pickingFrameBuffer == 4 ? 1f : 0.75f)); //BACK
GL.TexCoord2(0.75f, 0.0f);
GL.Vertex3(-1f, 1f, -1f);
GL.TexCoord2(0.5f, 0.0f);
GL.Vertex3(1f, 1f, -1f);
GL.TexCoord2(0.5f, 0.5f);
GL.Vertex3(1f, -1f, -1f);
GL.TexCoord2(0.75f, 0.5f);
GL.Vertex3(-1f, -1f, -1f);
GL.Color3(new Vector3(pickingFrameBuffer == 5 ? 1f : 0.75f)); //LEFT
GL.TexCoord2(0.5f, 0f);
GL.Vertex3(1f, 1f, -1f);
GL.TexCoord2(0.25f, 0f);
GL.Vertex3(1f, 1f, 1f);
GL.TexCoord2(0.25f, 0.5f);
GL.Vertex3(1f, -1f, 1f);
GL.TexCoord2(0.5f, 0.5f);
GL.Vertex3(1f, -1f, -1f);
GL.Color3(new Vector3(pickingFrameBuffer == 6 ? 1f : 0.75f)); //RIGHT
GL.TexCoord2(1f, 0f);
GL.Vertex3(-1f, 1f, 1f);
GL.TexCoord2(0.75f, 0f);
GL.Vertex3(-1f, 1f, -1f);
GL.TexCoord2(0.75f, 0.5f);
GL.Vertex3(-1f, -1f, -1f);
GL.TexCoord2(1f, 0.5f);
GL.Vertex3(-1f, -1f, 1f);
GL.End();
GL.Enable(EnableCap.DepthTest);
}
protected void DrawGradientBG()
{
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Lequal);
GL.Disable(EnableCap.Texture2D);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
GL.Begin(PrimitiveType.TriangleStrip);
GL.Color3(BackgroundColor2);
GL.Vertex3(1, 1, 0.99998);
GL.Vertex3(-1, 1, 0.99998);
GL.Color3(BackgroundColor1);
GL.Vertex3(1, -1, 0.99998);
GL.Vertex3(-1, -1, 0.99998);
GL.End();
GL.Enable(EnableCap.Texture2D);
}
public override void Refresh()
{
if(redrawerOwners==0) //Redrawer is deactivated?
base.Refresh(); //event can force a redraw
}
public void AttachRedrawer()
{
if (redrawerOwners == 0)
redrawer.Start();
redrawerOwners++;
}
public void AttachPickingRedrawer()
{
if (redrawerOwners == 0)
redrawer.Start();
repickerOwners++;
redrawerOwners++;
}
public void DetachRedrawer()
{
redrawerOwners--;
if (redrawerOwners == 0)
{
RedrawerFrame = 0;
redrawer.Stop();
}
}
public void DetachPickingRedrawer()
{
redrawerOwners--;
repickerOwners--;
if (redrawerOwners == 0)
{
RedrawerFrame = 0;
redrawer.Stop();
}
}
}
}

View file

@ -0,0 +1,302 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using GL_EditorFramework.Interfaces;
using GL_EditorFramework.StandardCameras;
namespace GL_EditorFramework.GL_Core
{
public class GL_ControlLegacy : GL_ControlBase
{
public GL_ControlLegacy(int redrawerInterval) : base(1, redrawerInterval)
{
}
public GL_ControlLegacy() : base(1, 16)
{
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (DesignMode) return;
MakeCurrent();
Framework.Initialize();
}
public override AbstractGlDrawable MainDrawable
{
get => mainDrawable;
set
{
if (value == null || DesignMode) return;
mainDrawable = value;
MakeCurrent();
mainDrawable.Prepare(this);
Refresh();
}
}
public override void UpdateModelMatrix(Matrix4 matrix)
{
if (DesignMode) return;
mtxMdl = matrix;
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref mtxMdl);
}
public override void ApplyModelTransform(Matrix4 matrix)
{
if (DesignMode) return;
mtxMdl *= matrix;
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref mtxMdl);
}
public override void ResetModelMatrix()
{
if (DesignMode) return;
mtxMdl = Matrix4.Identity;
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref mtxMdl);
}
protected override void OnPaint(PaintEventArgs e)
{
if (mainDrawable == null || DesignMode)
{
e.Graphics.Clear(this.BackColor);
e.Graphics.DrawString("Legacy Gl" + (stereoscopy ? " stereoscopy" : ""), SystemFonts.DefaultFont, SystemBrushes.ControlLight, 10f, 10f);
return;
}
MakeCurrent();
GL.ClearColor(BackgroundColor1);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
if (stereoscopy)
{
#region left eye
GL.Viewport(0, 0, Width / 2, Height);
ResetModelMatrix();
mtxCam =
Matrix4.CreateTranslation(camTarget) *
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateTranslation(0.25f, 0, camDistance) *
Matrix4.CreateRotationY(0.02f);
GL.MatrixMode(MatrixMode.Projection);
Matrix4 computedMatrix = mtxCam * mtxProj;
GL.LoadMatrix(ref computedMatrix);
mainDrawable.Draw(this, Pass.OPAQUE);
mainDrawable.Draw(this, Pass.TRANSPARENT);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
if (GradientBackground)
DrawGradientBG();
if (showOrientationCube)
{
GL.MatrixMode(MatrixMode.Modelview);
orientationCubeMtx =
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateScale(80f / Width, 40f / Height, 0.25f) *
Matrix4.CreateTranslation(1 - 160f / Width, 1 - 80f / Height, 0) *
Matrix4.CreateRotationY(0.03125f);
GL.LoadMatrix(ref orientationCubeMtx);
DrawOrientationCube();
}
if (showFakeCursor)
DrawFakeCursor();
#endregion
#region right eye
GL.Viewport(Width / 2, 0, Width / 2, Height);
ResetModelMatrix();
mtxCam =
Matrix4.CreateTranslation(camTarget) *
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateTranslation(-0.25f, 0, camDistance) *
Matrix4.CreateRotationY(-0.02f);
GL.MatrixMode(MatrixMode.Projection);
computedMatrix = mtxCam * mtxProj;
GL.LoadMatrix(ref computedMatrix);
mainDrawable.Draw(this, Pass.OPAQUE);
mainDrawable.Draw(this, Pass.TRANSPARENT);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
if (GradientBackground)
DrawGradientBG();
if (showOrientationCube)
{
GL.MatrixMode(MatrixMode.Modelview);
orientationCubeMtx =
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateScale(80f / Width, 40f / Height, 0.25f) *
Matrix4.CreateTranslation(1 - 160f / Width, 1 - 80f / Height, 0) *
Matrix4.CreateRotationY(-0.03125f);
GL.LoadMatrix(ref orientationCubeMtx);
DrawOrientationCube();
}
if (showFakeCursor)
DrawFakeCursor();
#endregion
}
else
{
GL.Viewport(0, 0, Width, Height);
ResetModelMatrix();
mtxCam =
Matrix4.CreateTranslation(camTarget) *
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateTranslation(0, 0, camDistance);
GL.MatrixMode(MatrixMode.Projection);
Matrix4 computedMatrix = mtxCam * mtxProj;
GL.LoadMatrix(ref computedMatrix);
mainDrawable.Draw(this, Pass.OPAQUE);
mainDrawable.Draw(this, Pass.TRANSPARENT);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
if (GradientBackground)
DrawGradientBG();
if (showOrientationCube)
{
GL.MatrixMode(MatrixMode.Modelview);
orientationCubeMtx =
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateScale(40f / Width, 40f / Height, 0.25f) *
Matrix4.CreateTranslation(1 - 80f / Width, 1 - 80f / Height, 0);
GL.LoadMatrix(ref orientationCubeMtx);
DrawOrientationCube();
}
}
SwapBuffers();
}
public override void DrawPicking()
{
if (DesignMode) return;
MakeCurrent();
GL.ClearColor(0f, 0f, 0f, 0f);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
if (stereoscopy)
GL.Viewport(0, 0, Width / 2, Height);
else
GL.Viewport(0, 0, Width, Height);
ResetModelMatrix();
mtxCam =
Matrix4.CreateTranslation(camTarget) *
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateTranslation(0, 0, camDistance);
GL.MatrixMode(MatrixMode.Projection);
Matrix4 computedMatrix = mtxCam * mtxProj;
GL.LoadMatrix(ref computedMatrix);
if (showOrientationCube)
skipPickingColors(6); //the orientation cube faces
mainDrawable.Draw(this, Pass.PICKING);
if (showOrientationCube)
{
GL.Disable(EnableCap.Texture2D);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.MatrixMode(MatrixMode.Modelview);
orientationCubeMtx =
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateScale((stereoscopy ? 80f : 40f) / Width, 40f / Height, 0.25f) *
Matrix4.CreateTranslation(1 - (stereoscopy ? 160f : 80f) / Width, 1 - 80f / Height, 0);
GL.LoadMatrix(ref orientationCubeMtx);
GL.Disable(EnableCap.DepthTest);
GL.Begin(PrimitiveType.Quads);
GL.Color4(Color.FromArgb(1)); //UP
GL.Vertex3(-1f, 1f, 1f);
GL.Vertex3(1f, 1f, 1f);
GL.Vertex3(1f, 1f, -1f);
GL.Vertex3(-1f, 1f, -1f);
GL.Color4(Color.FromArgb(2)); //DOWN
GL.Vertex3(-1f, -1f, -1f);
GL.Vertex3(1f, -1f, -1f);
GL.Vertex3(1f, -1f, 1f);
GL.Vertex3(-1f, -1f, 1f);
GL.Color4(Color.FromArgb(3)); //FRONT
GL.Vertex3(1f, 1f, 1f);
GL.Vertex3(-1f, 1f, 1f);
GL.Vertex3(-1f, -1f, 1f);
GL.Vertex3(1f, -1f, 1f);
GL.Color4(Color.FromArgb(4)); //BACK
GL.Vertex3(-1f, 1f, -1f);
GL.Vertex3(1f, 1f, -1f);
GL.Vertex3(1f, -1f, -1f);
GL.Vertex3(-1f, -1f, -1f);
GL.Color4(Color.FromArgb(5)); //LEFT
GL.Vertex3(1f, 1f, -1f);
GL.Vertex3(1f, 1f, 1f);
GL.Vertex3(1f, -1f, 1f);
GL.Vertex3(1f, -1f, -1f);
GL.Color4(Color.FromArgb(6)); //RIGHT
GL.Vertex3(-1f, 1f, 1f);
GL.Vertex3(-1f, 1f, -1f);
GL.Vertex3(-1f, -1f, -1f);
GL.Vertex3(-1f, -1f, 1f);
GL.End();
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.Texture2D);
}
}
}
}

View file

@ -0,0 +1,327 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using GL_EditorFramework.Interfaces;
using GL_EditorFramework.StandardCameras;
namespace GL_EditorFramework.GL_Core
{
public class GL_ControlModern : GL_ControlBase
{
public GL_ControlModern(int redrawerInterval) : base(3, redrawerInterval)
{
}
public GL_ControlModern() : base(3, 16)
{
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (DesignMode) return;
MakeCurrent();
Framework.Initialize();
}
private ShaderProgram shader;
public ShaderProgram CurrentShader
{
get => shader;
set
{
if (value == null || value == shader || DesignMode) return;
shader = value;
shader.Setup(mtxMdl, mtxCam, mtxProj);
}
}
public override AbstractGlDrawable MainDrawable
{
get => mainDrawable;
set
{
if (value == null || DesignMode) return;
mainDrawable = value;
MakeCurrent();
mainDrawable.Prepare(this);
Refresh();
}
}
public void ReloadShaders()
{
if (mainDrawable != null)
{
mainDrawable.Prepare(this);
Refresh();
}
}
public override void UpdateModelMatrix(Matrix4 matrix)
{
if (DesignMode) return;
mtxMdl = matrix;
if (shader!=null)
shader.UpdateModelMatrix(matrix);
}
public override void ApplyModelTransform(Matrix4 matrix)
{
if (DesignMode) return;
shader.UpdateModelMatrix(mtxMdl *= matrix);
}
public override void ResetModelMatrix()
{
if (DesignMode) return;
shader.UpdateModelMatrix(mtxMdl = Matrix4.Identity);
}
protected override void OnResize(EventArgs e)
{
if (DesignMode)
{
base.OnResize(e);
return;
}
MakeCurrent();
float aspect_ratio;
if (stereoscopy)
aspect_ratio = Width / 2 / (float)Height;
else
aspect_ratio = Width / (float)Height;
mtxProj = Matrix4.CreatePerspectiveFieldOfView(fov, aspect_ratio, znear, zfar);
orientationCubeMtx = Matrix4.CreateOrthographic(Width, Height, 0.125f, 2f) * Matrix4.CreateTranslation(0, 0, 1);
//using the calculation from whitehole
factorX = (2f * (float)Math.Tan(fov * 0.5f) * aspect_ratio) / Width;
factorY = (2f * (float)Math.Tan(fov * 0.5f)) / Height;
base.OnResize(e);
}
protected override void OnPaint(PaintEventArgs e)
{
if (mainDrawable == null || DesignMode)
{
base.OnPaint(e);
e.Graphics.Clear(Color.Black);
e.Graphics.DrawString("Modern Gl" + (stereoscopy ? " stereoscopy" : ""), SystemFonts.DefaultFont, SystemBrushes.ControlLight, 10f, 10f);
return;
}
MakeCurrent();
base.OnPaint(e);
GL.ClearColor(BackgroundColor1);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.MatrixMode(MatrixMode.Modelview);
if (stereoscopy)
{
#region left eye
GL.Viewport(0, 0, Width / 2, Height);
mtxMdl = Matrix4.Identity;
mtxCam =
Matrix4.CreateTranslation(camTarget) *
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateTranslation(0.25f, 0, camDistance) *
Matrix4.CreateRotationY(0.02f);
mainDrawable.Draw(this, Pass.OPAQUE);
mainDrawable.Draw(this, Pass.TRANSPARENT);
shader = null;
GL.UseProgram(0);
if (GradientBackground)
DrawGradientBG();
if (showOrientationCube)
{
orientationCubeMtx =
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateScale(80f / Width, 40f / Height, 0.25f) *
Matrix4.CreateTranslation(1 - 160f / Width, 1 - 80f / Height, 0) *
Matrix4.CreateRotationY(0.03125f);
GL.LoadMatrix(ref orientationCubeMtx);
DrawOrientationCube();
}
if (showFakeCursor)
DrawFakeCursor();
#endregion
#region right eye
GL.Viewport(Width / 2, 0, Width / 2, Height);
mtxMdl = Matrix4.Identity;
mtxCam =
Matrix4.CreateTranslation(camTarget) *
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateTranslation(-0.25f, 0, camDistance) *
Matrix4.CreateRotationY(-0.02f);
mainDrawable.Draw(this, Pass.OPAQUE);
mainDrawable.Draw(this, Pass.TRANSPARENT);
shader = null;
GL.UseProgram(0);
if (GradientBackground)
DrawGradientBG();
if (showOrientationCube)
{
orientationCubeMtx =
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateScale(80f / Width, 40f / Height, 0.25f) *
Matrix4.CreateTranslation(1 - 160f / Width, 1 - 80f / Height, 0) *
Matrix4.CreateRotationY(-0.03125f);
GL.LoadMatrix(ref orientationCubeMtx);
DrawOrientationCube();
}
if (showFakeCursor)
DrawFakeCursor();
#endregion
}
else
{
GL.Viewport(0, 0, Width, Height);
mtxMdl = Matrix4.Identity;
mtxCam =
Matrix4.CreateTranslation(camTarget) *
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateTranslation(0, 0, camDistance);
mainDrawable.Draw(this, Pass.OPAQUE);
mainDrawable.Draw(this, Pass.TRANSPARENT);
shader = null;
GL.UseProgram(0);
if (GradientBackground)
DrawGradientBG();
if (showOrientationCube)
{
orientationCubeMtx =
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateScale(40f / Width, 40f / Height, 0.25f) *
Matrix4.CreateTranslation(1 - 80f / Width, 1 - 80f / Height, 0);
GL.LoadMatrix(ref orientationCubeMtx);
DrawOrientationCube();
}
}
SwapBuffers();
}
public override void DrawPicking()
{
if (DesignMode) return;
MakeCurrent();
GL.ClearColor(0f, 0f, 0f, 0f);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
if (stereoscopy)
GL.Viewport(0, 0, Width / 2, Height);
else
GL.Viewport(0, 0, Width, Height);
if (showOrientationCube)
skipPickingColors(6); //the orientation cube faces
mainDrawable.Draw(this, Pass.PICKING);
if (showOrientationCube)
{
GL.UseProgram(0);
GL.Disable(EnableCap.Texture2D);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.MatrixMode(MatrixMode.Modelview);
orientationCubeMtx =
Matrix4.CreateRotationY(camRotX) *
Matrix4.CreateRotationX(camRotY) *
Matrix4.CreateScale((stereoscopy ? 80f : 40f) / Width, 40f / Height, 0.25f) *
Matrix4.CreateTranslation(1 - (stereoscopy ? 160f : 80f) / Width, 1 - 80f / Height, 0);
GL.LoadMatrix(ref orientationCubeMtx);
GL.Disable(EnableCap.DepthTest);
GL.Begin(PrimitiveType.Quads);
GL.Color4(Color.FromArgb(1)); //UP
GL.Vertex3(-1f, 1f, 1f);
GL.Vertex3(1f, 1f, 1f);
GL.Vertex3(1f, 1f, -1f);
GL.Vertex3(-1f, 1f, -1f);
GL.Color4(Color.FromArgb(2)); //DOWN
GL.Vertex3(-1f, -1f, -1f);
GL.Vertex3(1f, -1f, -1f);
GL.Vertex3(1f, -1f, 1f);
GL.Vertex3(-1f, -1f, 1f);
GL.Color4(Color.FromArgb(3)); //FRONT
GL.Vertex3(1f, 1f, 1f);
GL.Vertex3(-1f, 1f, 1f);
GL.Vertex3(-1f, -1f, 1f);
GL.Vertex3(1f, -1f, 1f);
GL.Color4(Color.FromArgb(4)); //BACK
GL.Vertex3(-1f, 1f, -1f);
GL.Vertex3(1f, 1f, -1f);
GL.Vertex3(1f, -1f, -1f);
GL.Vertex3(-1f, -1f, -1f);
GL.Color4(Color.FromArgb(5)); //LEFT
GL.Vertex3(1f, 1f, -1f);
GL.Vertex3(1f, 1f, 1f);
GL.Vertex3(1f, -1f, 1f);
GL.Vertex3(1f, -1f, -1f);
GL.Color4(Color.FromArgb(6)); //RIGHT
GL.Vertex3(-1f, 1f, 1f);
GL.Vertex3(-1f, 1f, -1f);
GL.Vertex3(-1f, -1f, -1f);
GL.Vertex3(-1f, -1f, 1f);
GL.End();
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.Texture2D);
}
}
}
}

View file

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL;
namespace GL_EditorFramework.GL_Core
{
public class OldGlEmulator : IDisposable
{
List<float> dataList = new List<float>();
float current_r = 255f;
float current_g = 255f;
float current_b = 255f;
float current_a = 255f;
public OldGlEmulator()
{
}
public void Vertex3(float x, float y, float z)
{
dataList.Add(x); dataList.Add(y); dataList.Add(z);
dataList.Add(current_r); dataList.Add(current_g); dataList.Add(current_b); dataList.Add(current_a);
}
public void Color3(float r, float g, float b)
{
current_r = r;
current_g = g;
current_b = b;
}
public void WriteToBuffer(int buffer) {
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
float[] arrayData = dataList.ToArray();
GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * arrayData.Length, arrayData, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 7, 0);
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, sizeof(float) * 7, sizeof(float) * 3);
}
public void Dispose()
{
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View file

@ -0,0 +1,262 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace GL_EditorFramework.GL_Core
{
public class ShaderProgram
{
private int fragSh, vertSh, geomSh;
private Matrix4 modelMatrix;
private Matrix4 computedCamMtx;
private Matrix4 projectionMatrix;
private Dictionary<string, int> attributes = new Dictionary<string, int>();
private int activeAttributeCount;
public int program;
public ShaderProgram(FragmentShader frag, VertexShader vert)
{
LoadShaders(new Shader[] { vert, frag });
}
public ShaderProgram(FragmentShader frag, VertexShader vert, GeomertyShader geom)
{
LoadShaders(new Shader[] { vert, frag, geom });
}
public ShaderProgram(Shader[] shaders)
{
LoadShaders(shaders);
}
private void LoadShaders(Shader[] shaders)
{
program = GL.CreateProgram();
foreach (Shader shader in shaders)
{
AttachShader(shader);
}
GL.LinkProgram(program);
foreach (Shader shader in shaders)
{
if (shader.type == ShaderType.VertexShader)
Console.WriteLine("vertex:");
if (shader.type == ShaderType.FragmentShader)
Console.WriteLine("fragment:");
if (shader.type == ShaderType.GeometryShader)
Console.WriteLine("geometry:");
Console.WriteLine(GL.GetShaderInfoLog(shader.id));
}
LoadAttributes();
}
public void AttachShader(Shader shader)
{
Console.WriteLine("shader:");
Console.WriteLine(GL.GetShaderInfoLog(shader.id));
GL.AttachShader(program, shader.id);
}
public void DetachShader(Shader shader)
{
GL.DetachShader(program, shader.id);
}
public void LinkShaders()
{
GL.LinkProgram(program);
}
public void SetFragmentShader(FragmentShader shader)
{
GL.DetachShader(program, fragSh);
GL.AttachShader(program, shader.id);
fragSh = shader.id;
GL.LinkProgram(program);
}
public void SetVertexShader(VertexShader shader)
{
GL.DetachShader(program, vertSh);
GL.AttachShader(program, shader.id);
vertSh = shader.id;
GL.LinkProgram(program);
GL.UniformMatrix4(GL.GetUniformLocation(program, "mtxMdl"), false, ref modelMatrix);
GL.UniformMatrix4(GL.GetUniformLocation(program, "mtxCam"), false, ref computedCamMtx);
}
public void Setup(Matrix4 mtxMdl, Matrix4 mtxCam, Matrix4 mtxProj)
{
GL.UseProgram(program);
modelMatrix = mtxMdl;
int mtxMdl_loc = GL.GetUniformLocation(program, "mtxMdl");
if (mtxMdl_loc != -1)
GL.UniformMatrix4(mtxMdl_loc, false, ref modelMatrix);
computedCamMtx = mtxCam * mtxProj;
int mtxCam_loc = GL.GetUniformLocation(program, "mtxCam");
if (mtxCam_loc != -1)
GL.UniformMatrix4(mtxCam_loc, false, ref computedCamMtx);
int mtxCamTest_loc = GL.GetUniformLocation(program, "mtxCamTest");
if (mtxCamTest_loc != -1)
GL.UniformMatrix4(mtxCamTest_loc, false, ref mtxCam);
projectionMatrix = mtxProj;
int projCam_loc = GL.GetUniformLocation(program, "mtxProj");
if (projCam_loc != -1)
GL.UniformMatrix4(projCam_loc, false, ref projectionMatrix);
}
public void UpdateModelMatrix(Matrix4 matrix)
{
modelMatrix = matrix;
int mtxMdl_loc = GL.GetUniformLocation(program, "mtxMdl");
if (mtxMdl_loc != -1)
GL.UniformMatrix4(mtxMdl_loc, false, ref modelMatrix);
}
public void Activate()
{
GL.UseProgram(program);
}
public int this[string name]
{
get => GL.GetUniformLocation(program, name);
}
private void LoadAttributes()
{
attributes.Clear();
GL.GetProgram(program, GetProgramParameterName.ActiveAttributes, out activeAttributeCount);
for (int i = 0; i < activeAttributeCount; i++)
AddAttribute(i);
}
private void AddAttribute(int index)
{
string name = GL.GetActiveAttrib(program, index, out int size, out ActiveAttribType type);
int location = GL.GetAttribLocation(program, name);
// Overwrite existing vertex attributes.
attributes[name] = location;
}
public int GetAttribute(string name)
{
if (string.IsNullOrEmpty(name) || !attributes.ContainsKey(name))
return -1;
else
return attributes[name];
}
public void EnableVertexAttributes()
{
foreach (KeyValuePair<string, int> attrib in attributes)
{
GL.EnableVertexAttribArray(attrib.Value);
}
}
public void DisableVertexAttributes()
{
foreach (KeyValuePair<string, int> attrib in attributes)
{
GL.DisableVertexAttribArray(attrib.Value);
}
}
public void SetBoolToInt(string name, bool value)
{
if (value)
GL.Uniform1(this[name], 1);
else
GL.Uniform1(this[name], 0);
}
public void SetMatrix4x4(string name, ref Matrix4 value, bool Transpose = false)
{
GL.UniformMatrix4(this[name], false, ref value);
}
public void SetVector4(string name, Vector4 value)
{
GL.Uniform4(this[name], value);
}
public void SetVector3(string name, Vector3 value)
{
GL.Uniform3(this[name], value);
}
public void SetVector2(string name, Vector2 value)
{
GL.Uniform2(this[name], value);
}
public void SetFloat(string name, float value)
{
GL.Uniform1(this[name], value);
}
public void SetInt(string name, int value)
{
GL.Uniform1(this[name], value);
}
}
public class Shader
{
public Shader(string src, ShaderType type)
{
id = GL.CreateShader(type);
GL.ShaderSource(id, src);
GL.CompileShader(id);
this.type = type;
}
public ShaderType type;
public int id;
}
public class FragmentShader : Shader
{
public FragmentShader(string src)
: base(src, ShaderType.FragmentShader)
{
}
}
public class VertexShader : Shader
{
public VertexShader(string src)
: base(src, ShaderType.VertexShader)
{
}
}
public class GeomertyShader : Shader
{
public GeomertyShader(string src)
: base(src, ShaderType.GeometryShader)
{
}
}
}

View file

@ -0,0 +1,96 @@
<?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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D593A72D-554D-40FB-9967-503CB15A744F}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenGl_EditorFramework</RootNamespace>
<AssemblyName>OpenGl_EditorFramework</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="OpenTK">
<HintPath>..\..\Toolbox\Lib\OpenTK.dll</HintPath>
</Reference>
<Reference Include="OpenTK.GLControl">
<HintPath>..\..\Toolbox\Lib\OpenTK.GLControl.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="EditorDrawables\SingleObject.cs" />
<Compile Include="GL_Core\Cameras\Inspect.cs" />
<Compile Include="GL_Core\Cameras\Walkaround.cs" />
<Compile Include="EditorDrawables\EditableObject.cs" />
<Compile Include="EditorDrawables\EditorScene.cs" />
<Compile Include="EditorDrawables\Path.cs" />
<Compile Include="Framework.cs" />
<Compile Include="GL_Core\GL_ControlBase.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="GL_Core\GL_ControlLegacy.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="GL_Core\GL_ControlModern.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="GL_Core\OldGlEmulator.cs" />
<Compile Include="Interfaces\AbstractCamera.cs" />
<Compile Include="Interfaces\AbstractEventHandlingObj.cs" />
<Compile Include="Interfaces\AbstractGlDrawable.cs" />
<Compile Include="Interfaces\I3DControl.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Renderers.cs" />
<Compile Include="SceneListView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="GL_Core\ShaderClass.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="GL_Core\Resources\TextureSheet.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,40 @@
using OpenTK;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GL_EditorFramework.Interfaces
{
public abstract class AbstractCamera : AbstractEventHandling3DObj
{
public const uint UPDATE_CAMERA = 0x80000000;
private const float depthAdjust = 1;
protected float depth, desiredDepth;
public override uint MouseDown(MouseEventArgs e, I3DControl control)
{
desiredDepth = control.PickingDepth;
return 0;
}
public override uint MouseMove(MouseEventArgs e, Point lastMouseLoc, I3DControl control)
{
if (e.Button == MouseButtons.Left)
{
if (depth < desiredDepth - depthAdjust)
depth += depthAdjust;
else if (depth != desiredDepth)
depth = desiredDepth;
}
return 0;
}
public virtual void Update() { }
}
}

View file

@ -0,0 +1,23 @@
using GL_EditorFramework.GL_Core;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GL_EditorFramework.Interfaces
{
public class AbstractEventHandling3DObj
{
public virtual uint MouseDown(MouseEventArgs e, I3DControl control) { return 0; }
public virtual uint MouseMove(MouseEventArgs e, Point lastMousePos, I3DControl control) {return 0; }
public virtual uint MouseUp(MouseEventArgs e, I3DControl control) { return 0; }
public virtual uint MouseWheel(MouseEventArgs e, I3DControl control) { return 0; }
public virtual uint MouseClick(MouseEventArgs e, I3DControl control) { return 0; }
public virtual uint KeyDown(KeyEventArgs e, I3DControl control) { return 0; }
public virtual uint KeyUp(KeyEventArgs e, I3DControl control) { return 0; }
}
}

View file

@ -0,0 +1,36 @@
using GL_EditorFramework.GL_Core;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GL_EditorFramework.Interfaces
{
public enum Pass
{
OPAQUE,
TRANSPARENT,
PICKING
}
public abstract class AbstractGlDrawable : AbstractEventHandling3DObj
{
public const uint REDRAW = 0x80000000;
public const uint REDRAW_PICKING = 0xC0000000;
public const uint NO_CAMERA_ACTION = 0x20000000;
public const uint REPICK = 0x40000000;
public abstract void Prepare(GL_ControlModern control);
public abstract void Prepare(GL_ControlLegacy control);
public abstract void Draw(GL_ControlModern control, Pass pass);
public abstract void Draw(GL_ControlLegacy control, Pass pass);
public virtual int GetPickableSpan() => 1;
public virtual uint MouseEnter(int index, I3DControl control) { return 0; }
public virtual uint MouseLeave(int index, I3DControl control) { return 0; }
public virtual uint MouseLeaveEntirely(I3DControl control) { return 0; }
public override uint MouseMove(MouseEventArgs e, Point lastMousePos, I3DControl control) { return REPICK; }
}
}

View file

@ -0,0 +1,45 @@
using OpenTK;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GL_EditorFramework.Interfaces
{
public interface I3DControl
{
void AttachRedrawer();
void AttachPickingRedrawer();
void DetachRedrawer();
void DetachPickingRedrawer();
ulong RedrawerFrame { get; }
int ViewWidth { get; }
int ViewHeighth { get; }
Vector2 NormMouseCoords(int x, int y);
Point DragStartPos { get; set; }
float ZFar { get; set; }
float ZNear { get; set; }
float Fov { get; set; }
float FactorX { get; }
float FactorY { get; }
Vector3 CameraTarget { get; set; }
float CameraDistance { get; set; }
float CamRotX { get; set; }
float CamRotY { get; set; }
Vector3 coordFor(int x, int y, float depth);
Vector3 screenCoordFor(Vector3 coord);
float PickingDepth { get; }
float NormPickingDepth { get; }
}
}

View file

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("OpenGl_EditorFramework")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OpenGl_EditorFramework")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("d593a72d-554d-40fb-9967-503cb15a744f")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace OpenGl_EditorFramework.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpenGl_EditorFramework.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap TextureSheet {
get {
object obj = ResourceManager.GetObject("TextureSheet", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View file

@ -0,0 +1,124 @@
<?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.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="TextureSheet" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\GL_Core\Resources\TextureSheet.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View file

@ -0,0 +1,464 @@
using GL_EditorFramework;
using GL_EditorFramework.GL_Core;
using GL_EditorFramework.Interfaces;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenGl_EditorFramework
{
public static class Renderers
{
private static void face(ref float[][] points, ref List<float> data, int p1, int p2, int p4, int p3)
{
data.AddRange(new float[] {
points[p1][0], points[p1][1], points[p1][2],
points[p2][0], points[p2][1], points[p2][2],
points[p3][0], points[p3][1], points[p3][2],
points[p4][0], points[p4][1], points[p4][2]
});
}
private static void lineFace(ref float[][] points, ref List<float> data, int p1, int p2, int p4, int p3)
{
data.AddRange(new float[] {
points[p1][0], points[p1][1], points[p1][2],
points[p2][0], points[p2][1], points[p2][2],
points[p2][0], points[p2][1], points[p2][2],
points[p3][0], points[p3][1], points[p3][2],
points[p3][0], points[p3][1], points[p3][2],
points[p4][0], points[p4][1], points[p4][2],
points[p4][0], points[p4][1], points[p4][2],
points[p1][0], points[p1][1], points[p1][2]
});
}
private static void line(ref float[][] points, ref List<float> data, int p1, int p2)
{
data.AddRange(new float[] {
points[p1][0], points[p1][1], points[p1][2],
points[p2][0], points[p2][1], points[p2][2]
});
}
private static void faceInv(ref float[][] points, ref List<float> data, int p2, int p1, int p3, int p4)
{
data.AddRange(new float[] {
points[p1][0], points[p1][1], points[p1][2],
points[p2][0], points[p2][1], points[p2][2],
points[p3][0], points[p3][1], points[p3][2],
points[p4][0], points[p4][1], points[p4][2]
});
}
public static class ColorBlockRenderer {
private static bool Initialized = false;
private static ShaderProgram defaultShaderProgram;
private static ShaderProgram solidColorShaderProgram;
private static int linesVao;
private static int blockVao;
private static float[][] points = new float[][]
{
new float[]{-1,-1, 1},
new float[]{ 1,-1, 1},
new float[]{-1, 1, 1},
new float[]{ 1, 1, 1},
new float[]{-1,-1,-1},
new float[]{ 1,-1,-1},
new float[]{-1, 1,-1},
new float[]{ 1, 1,-1}
};
public static void Initialize()
{
if (!Initialized)
{
var defaultFrag = new FragmentShader(
@"#version 330
uniform sampler2D tex;
in vec4 fragColor;
in vec3 fragPosition;
in vec2 uv;
void main(){
gl_FragColor = fragColor*((fragPosition.y+2)/3)*texture(tex, uv);
}");
var solidColorFrag = new FragmentShader(
@"#version 330
uniform vec4 color;
void main(){
gl_FragColor = color;
}");
var defaultVert = new VertexShader(
@"#version 330
layout(location = 0) in vec4 position;
uniform vec4 color;
uniform mat4 mtxMdl;
uniform mat4 mtxCam;
out vec4 fragColor;
out vec3 fragPosition;
out vec2 uv;
vec2 map(vec2 value, vec2 min1, vec2 max1, vec2 min2, vec2 max2) {
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
}
void main(){
fragPosition = position.xyz;
uv = map(fragPosition.xz,vec2(-1.0625,-1.0625),vec2(1.0625,1.0625), vec2(0.5,0.5), vec2(0.75,1.0));
gl_Position = mtxCam*mtxMdl*position;
fragColor = color;
}");
var solidColorVert = new VertexShader(
@"#version 330
layout(location = 0) in vec4 position;
uniform mat4 mtxMdl;
uniform mat4 mtxCam;
void main(){
gl_Position = mtxCam*mtxMdl*position;
}");
defaultShaderProgram = new ShaderProgram(defaultFrag, defaultVert);
solidColorShaderProgram = new ShaderProgram(solidColorFrag, solidColorVert);
int buffer;
#region block
GL.BindVertexArray(blockVao = GL.GenVertexArray());
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer = GL.GenBuffer());
List<float> list = new List<float>();
face(ref points, ref list, 0, 1, 2, 3);
faceInv(ref points, ref list, 4, 5, 6, 7);
faceInv(ref points, ref list, 0, 1, 4, 5);
face(ref points, ref list, 2, 3, 6, 7);
face(ref points, ref list, 0, 2, 4, 6);
faceInv(ref points, ref list, 1, 3, 5, 7);
float[] data = list.ToArray();
GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * data.Length, data, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 3, 0);
#endregion
#region lines
GL.BindVertexArray(linesVao = GL.GenVertexArray());
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer = GL.GenBuffer());
list = new List<float>();
lineFace(ref points, ref list, 0, 1, 2, 3);
lineFace(ref points, ref list, 4, 5, 6, 7);
line(ref points, ref list, 0, 4);
line(ref points, ref list, 1, 5);
line(ref points, ref list, 2, 6);
line(ref points,
ref list, 3, 7);
data = list.ToArray();
GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * data.Length, data, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 3, 0);
#endregion
Initialized = true;
}
}
public static void Draw(GL_ControlModern control, Pass pass, Vector4 blockColor, Vector4 lineColor, Color pickingColor)
{
control.CurrentShader = solidColorShaderProgram;
if (pass == Pass.OPAQUE)
{
#region outlines
GL.LineWidth(2.0f);
GL.Uniform4(solidColorShaderProgram["color"], lineColor);
GL.BindVertexArray(linesVao);
GL.DrawArrays(PrimitiveType.Lines, 0, 24);
#endregion
control.CurrentShader = defaultShaderProgram;
GL.Uniform1(defaultShaderProgram["tex"], Framework.TextureSheet - 1);
GL.Uniform4(defaultShaderProgram["color"], blockColor);
}
else
GL.Uniform4(solidColorShaderProgram["color"], pickingColor);
GL.BindVertexArray(blockVao);
GL.DrawArrays(PrimitiveType.Quads, 0, 24);
}
public static void Draw(GL_ControlLegacy control, Pass pass, Vector4 blockColor, Vector4 lineColor, Color pickingColor)
{
GL.Disable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, 0);
if (pass == Pass.OPAQUE)
{
#region draw lines
GL.Color4(lineColor);
GL.LineWidth(2.0f);
GL.Begin(PrimitiveType.LineStrip);
GL.Vertex3(points[6]);
GL.Vertex3(points[2]);
GL.Vertex3(points[3]);
GL.Vertex3(points[7]);
GL.Vertex3(points[6]);
GL.Vertex3(points[4]);
GL.Vertex3(points[5]);
GL.Vertex3(points[1]);
GL.Vertex3(points[0]);
GL.Vertex3(points[4]);
GL.End();
GL.Begin(PrimitiveType.Lines);
GL.Vertex3(points[2]);
GL.Vertex3(points[0]);
GL.Vertex3(points[3]);
GL.Vertex3(points[1]);
GL.Vertex3(points[7]);
GL.Vertex3(points[5]);
GL.End();
#endregion
}
else
{
GL.Color4(pickingColor);
GL.Begin(PrimitiveType.Quads);
GL.Vertex3(points[7]);
GL.Vertex3(points[6]);
GL.Vertex3(points[2]);
GL.Vertex3(points[3]);
GL.Vertex3(points[4]);
GL.Vertex3(points[5]);
GL.Vertex3(points[1]);
GL.Vertex3(points[0]);
GL.End();
GL.Begin(PrimitiveType.QuadStrip);
GL.Vertex3(points[7]);
GL.Vertex3(points[5]);
GL.Vertex3(points[6]);
GL.Vertex3(points[4]);
GL.Vertex3(points[2]);
GL.Vertex3(points[0]);
GL.Vertex3(points[3]);
GL.Vertex3(points[1]);
GL.Vertex3(points[7]);
GL.Vertex3(points[5]);
GL.End();
}
GL.Enable(EnableCap.Texture2D);
if (pass == Pass.OPAQUE)
{
GL.BindTexture(TextureTarget.Texture2D, Framework.TextureSheet);
#region draw faces
Vector4 darkerColor = blockColor * 0.71875f;
GL.Begin(PrimitiveType.Quads);
GL.Color4(blockColor);
GL.TexCoord2(0.71875f, 0.515625f);
GL.Vertex3(points[7]);
GL.TexCoord2(0.53125f, 0.515625f);
GL.Vertex3(points[6]);
GL.TexCoord2(0.53125f, 0.984375f);
GL.Vertex3(points[2]);
GL.TexCoord2(0.71875f, 0.984375f);
GL.Vertex3(points[3]);
GL.Color4(darkerColor);
GL.TexCoord2(0.53125f, 0.515625f);
GL.Vertex3(points[4]);
GL.TexCoord2(0.71875f, 0.515625f);
GL.Vertex3(points[5]);
GL.TexCoord2(0.71875f, 0.984375f);
GL.Vertex3(points[1]);
GL.TexCoord2(0.53125f, 0.984375f);
GL.Vertex3(points[0]);
GL.End();
GL.Begin(PrimitiveType.QuadStrip);
GL.TexCoord2(0.71875f, 0.515625f);
GL.Color4(blockColor);
GL.Vertex3(points[7]);
GL.Color4(darkerColor);
GL.Vertex3(points[5]);
GL.Color4(blockColor);
GL.Vertex3(points[6]);
GL.Color4(darkerColor);
GL.Vertex3(points[4]);
GL.Color4(blockColor);
GL.Vertex3(points[2]);
GL.Color4(darkerColor);
GL.Vertex3(points[0]);
GL.Color4(blockColor);
GL.Vertex3(points[3]);
GL.Color4(darkerColor);
GL.Vertex3(points[1]);
GL.Color4(blockColor);
GL.Vertex3(points[7]);
GL.Color4(darkerColor);
GL.Vertex3(points[5]);
GL.End();
#endregion
}
}
}
public static class LineBoxRenderer
{
private static bool Initialized = false;
private static ShaderProgram defaultShaderProgram;
private static int linesVao;
private static float[][] points = new float[][]
{
new float[]{-1,-1, 1},
new float[]{ 1,-1, 1},
new float[]{-1, 1, 1},
new float[]{ 1, 1, 1},
new float[]{-1,-1,-1},
new float[]{ 1,-1,-1},
new float[]{-1, 1,-1},
new float[]{ 1, 1,-1}
};
public static void Initialize()
{
if (!Initialized)
{
var defaultFrag = new FragmentShader(
@"#version 330
uniform vec4 color;
void main(){
gl_FragColor = color;
}");
var defaultVert = new VertexShader(
@"#version 330
layout(location = 0) in vec4 position;
uniform mat4 mtxMdl;
uniform mat4 mtxCam;
void main(){
gl_Position = mtxCam*mtxMdl*position;
}");
defaultShaderProgram = new ShaderProgram(defaultFrag, defaultVert);
int buffer;
#region lines
GL.BindVertexArray(linesVao = GL.GenVertexArray());
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer = GL.GenBuffer());
List<float> list = new List<float>();
lineFace(ref points, ref list, 0, 1, 2, 3);
lineFace(ref points, ref list, 4, 5, 6, 7);
line(ref points, ref list, 0, 4);
line(ref points, ref list, 1, 5);
line(ref points, ref list, 2, 6);
line(ref points, ref list, 3, 7);
float[] data = list.ToArray();
GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * data.Length, data, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float) * 3, 0);
#endregion
Initialized = true;
}
}
public static void Draw(GL_ControlModern control, Pass pass, Vector4 color, Color pickingColor)
{
control.CurrentShader = defaultShaderProgram;
if (pass == Pass.OPAQUE)
{
GL.LineWidth(4.0f);
GL.Uniform4(defaultShaderProgram["color"], color);
}
else
{
GL.LineWidth(6.0f);
GL.Uniform4(defaultShaderProgram["color"], pickingColor);
}
GL.BindVertexArray(linesVao);
GL.DrawArrays(PrimitiveType.Lines, 0, 24);
}
public static void Draw(GL_ControlLegacy control, Pass pass, Vector4 color, Color pickingColor)
{
GL.Disable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, 0);
if (pass == Pass.OPAQUE)
{
GL.LineWidth(4.0f);
GL.Color4(color);
}
else
{
GL.LineWidth(6.0f);
GL.Color4(pickingColor);
}
GL.Begin(PrimitiveType.LineStrip);
GL.Vertex3(points[6]);
GL.Vertex3(points[2]);
GL.Vertex3(points[3]);
GL.Vertex3(points[7]);
GL.Vertex3(points[6]);
GL.Vertex3(points[4]);
GL.Vertex3(points[5]);
GL.Vertex3(points[1]);
GL.Vertex3(points[0]);
GL.Vertex3(points[4]);
GL.End();
GL.Begin(PrimitiveType.Lines);
GL.Vertex3(points[2]);
GL.Vertex3(points[0]);
GL.Vertex3(points[3]);
GL.Vertex3(points[1]);
GL.Vertex3(points[7]);
GL.Vertex3(points[5]);
GL.End();
GL.Enable(EnableCap.Texture2D);
}
}
}
}

View file

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GL_EditorFramework
{
public partial class SceneListView : UserControl
{
public SceneListView()
{
}
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
Graphics g = e.Graphics;
Rectangle rect = new Rectangle(2, 2, Width - 4, 23);
g.FillRectangle(SystemBrushes.ControlLight, rect);
g.DrawRectangle(SystemPens.ControlDark, rect);
int yoff = (int)(Font.GetHeight(e.Graphics.DpiX)/2f);
g.DrawString("Category", Font, new SolidBrush(ForeColor), 4, 2+rect.Height/2-yoff);
rect = new Rectangle(2, 32, Width - 4, Height - 34);
g.FillRectangle(SystemBrushes.Window, rect);
g.DrawRectangle(SystemPens.ControlDarkDark, rect);
}
}
}

Binary file not shown.

View file

@ -0,0 +1,187 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GL_EditorFramework;
using GL_EditorFramework.EditorDrawables;
using GL_EditorFramework.GL_Core;
using GL_EditorFramework.Interfaces;
using OpenGl_EditorFramework;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace Testing
{
//This class is supposed to show of some very basic animation stuff you could do with this framework
//but it's highly recommended to add members like startTime and isPlaying if you want to make your own animated object class
class AnimatedObject : SingleObject
{
public AnimatedObject(Vector3 pos) : base(pos)
{
}
static new Vector4 Color = new Vector4(1f, 0f, 0f, 1f);
public override void Draw(GL_ControlModern control, Pass pass, EditorScene editorScene)
{
if (pass == Pass.TRANSPARENT)
return;
bool hovered = editorScene.hovered == this;
Matrix4 mtx = Matrix4.CreateScale(1f, 0.25f, 1f);
mtx *= Matrix4.CreateFromAxisAngle(Vector3.UnitY, -(float)Math.PI / 2f);
mtx *= Matrix4.CreateTranslation(Position + (Selected ? editorScene.deltaTransform.Translation : new Vector3()));
control.UpdateModelMatrix(mtx);
Color pickingColor = control.nextPickingColor();
Vector4 lineBoxColor;
if (hovered && Selected)
lineBoxColor = hoverColor;
else if (hovered || Selected)
lineBoxColor = selectColor;
else
lineBoxColor = new Vector4(1, 1, 1, 1);
Renderers.LineBoxRenderer.Draw(control, pass, lineBoxColor, pickingColor);
control.UpdateModelMatrix(mtx * Matrix4.CreateTranslation(Vector3.UnitX * 3f));
Renderers.LineBoxRenderer.Draw(control, pass, lineBoxColor, pickingColor);
control.UpdateModelMatrix(mtx * Matrix4.CreateTranslation(Vector3.UnitX * (3f - Math.Abs(control.RedrawerFrame * 0.0625f % 6f - 3f))));
Renderers.ColorBlockRenderer.Draw(control, pass, Color, Color, pickingColor);
}
public override void Draw(GL_ControlModern control, Pass pass)
{
if (pass == Pass.TRANSPARENT)
return;
Matrix4 mtx = Matrix4.CreateScale(1f, 0.25f, 1f);
mtx *= Matrix4.CreateFromAxisAngle(Vector3.UnitY, -(float)Math.PI / 2f);
mtx *= Matrix4.CreateTranslation(Position);
control.UpdateModelMatrix(mtx);
Color pickingColor = control.nextPickingColor();
Vector4 lineBoxColor = new Vector4(1, 1, 1, 1);
Renderers.LineBoxRenderer.Draw(control, pass, lineBoxColor, pickingColor);
control.UpdateModelMatrix(mtx * Matrix4.CreateTranslation(Vector3.UnitX * 3f));
Renderers.LineBoxRenderer.Draw(control, pass, lineBoxColor, pickingColor);
control.UpdateModelMatrix(mtx);
Renderers.ColorBlockRenderer.Draw(control, pass, Color, Color, pickingColor);
}
public override void Draw(GL_ControlLegacy control, Pass pass, EditorScene editorScene)
{
if (pass == Pass.TRANSPARENT)
return;
bool hovered = editorScene.hovered == this;
Matrix4 mtx = Matrix4.CreateScale(1f, 0.25f, 1f);
mtx *= Matrix4.CreateFromAxisAngle(Vector3.UnitY, (float)Math.PI / 2f);
mtx *= Matrix4.CreateTranslation(Position + (Selected ? editorScene.deltaTransform.Translation : new Vector3()));
control.UpdateModelMatrix(mtx);
Color pickingColor = control.nextPickingColor();
Vector4 lineBoxColor;
if (hovered && Selected)
lineBoxColor = hoverColor;
else if (hovered || Selected)
lineBoxColor = selectColor;
else
lineBoxColor = new Vector4(1, 1, 1, 1);
Renderers.LineBoxRenderer.Draw(control, pass, lineBoxColor, pickingColor);
control.UpdateModelMatrix(mtx * Matrix4.CreateTranslation(Vector3.UnitX * 3f));
Renderers.LineBoxRenderer.Draw(control, pass, lineBoxColor, pickingColor);
control.UpdateModelMatrix(mtx * Matrix4.CreateTranslation(Vector3.UnitX * (3f - Math.Abs(control.RedrawerFrame * 0.0625f % 6f - 3f))));
Renderers.ColorBlockRenderer.Draw(control, pass, Color, Color, pickingColor);
}
public override void Draw(GL_ControlLegacy control, Pass pass)
{
if (pass == Pass.TRANSPARENT)
return;
Matrix4 mtx = Matrix4.CreateScale(1f, 0.25f, 1f);
mtx *= Matrix4.CreateFromAxisAngle(Vector3.UnitY, -(float)Math.PI / 2f);
mtx *= Matrix4.CreateTranslation(Position);
control.UpdateModelMatrix(mtx);
Color pickingColor = control.nextPickingColor();
Vector4 lineBoxColor = new Vector4(1, 1, 1, 1);
Renderers.LineBoxRenderer.Draw(control, pass, lineBoxColor, pickingColor);
control.UpdateModelMatrix(mtx * Matrix4.CreateTranslation(Vector3.UnitX * 3f));
Renderers.LineBoxRenderer.Draw(control, pass, lineBoxColor, pickingColor);
control.UpdateModelMatrix(mtx);
Renderers.ColorBlockRenderer.Draw(control, pass, Color, Color, pickingColor);
}
public override void Prepare(GL_ControlModern control)
{
Renderers.LineBoxRenderer.Initialize();
base.Prepare(control);
}
public override uint Select(int index, I3DControl control)
{
Selected = true;
control.AttachPickingRedrawer();
return 0;
}
public override uint SelectDefault(I3DControl control)
{
Selected = true;
control.AttachPickingRedrawer();
return 0;
}
public override uint SelectAll(I3DControl control)
{
Selected = true;
control.AttachPickingRedrawer();
return 0;
}
public override uint Deselect(int index, I3DControl control)
{
Selected = false;
control.DetachPickingRedrawer();
return 0;
}
public override uint DeselectAll(I3DControl control)
{
Selected = false;
control.DetachPickingRedrawer();
return 0;
}
}
}

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>

View file

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Testing
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TestingForm());
}
}
}

View file

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Testing")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Testing")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("860b49c9-54e3-4e10-830d-6497b845ed11")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Testing.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Testing.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View file

@ -0,0 +1,117 @@
<?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.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: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" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</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" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Testing.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.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;
}
}
}
}

View file

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View file

@ -0,0 +1,96 @@
<?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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{860B49C9-54E3-4E10-830D-6497B845ED11}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>Testing</RootNamespace>
<AssemblyName>Testing</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</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>
<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>
<ItemGroup>
<Reference Include="OpenTK">
<HintPath>..\..\Toolbox\Lib\OpenTK.dll</HintPath>
</Reference>
<Reference Include="OpenTK.GLControl">
<HintPath>..\..\Toolbox\Lib\OpenTK.GLControl.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" />
</ItemGroup>
<ItemGroup>
<Compile Include="AnimatedObject.cs" />
<Compile Include="TestingForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="TestingForm.Designer.cs">
<DependentUpon>TestingForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="TestingForm.resx">
<DependentUpon>TestingForm.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">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<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" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Gl_EditorFramework\Gl_EditorFramework.csproj">
<Project>{d593a72d-554d-40fb-9967-503cb15a744f}</Project>
<Name>Gl_EditorFramework</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,128 @@
namespace Testing
{
partial class TestingForm
{
/// <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(TestingForm));
this.button1 = new System.Windows.Forms.Button();
this.listBox1 = new System.Windows.Forms.ListBox();
this.gL_ControlLegacy1 = new GL_EditorFramework.GL_Core.GL_ControlLegacy();
this.gL_ControlModern1 = new GL_EditorFramework.GL_Core.GL_ControlModern();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(12, 208);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 3;
this.button1.Text = "Add Object";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// listBox1
//
this.listBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point(13, 238);
this.listBox1.Name = "listBox1";
this.listBox1.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended;
this.listBox1.Size = new System.Drawing.Size(278, 498);
this.listBox1.TabIndex = 4;
//
// gL_ControlLegacy1
//
this.gL_ControlLegacy1.ActiveCamera = null;
this.gL_ControlLegacy1.BackColor = System.Drawing.Color.Black;
this.gL_ControlLegacy1.CameraDistance = -10F;
this.gL_ControlLegacy1.CameraTarget = ((OpenTK.Vector3)(resources.GetObject("gL_ControlLegacy1.CameraTarget")));
this.gL_ControlLegacy1.CamRotX = 0F;
this.gL_ControlLegacy1.CamRotY = 0F;
this.gL_ControlLegacy1.DragStartPos = new System.Drawing.Point(0, 0);
this.gL_ControlLegacy1.Fov = 0.7853982F;
this.gL_ControlLegacy1.Location = new System.Drawing.Point(13, 20);
this.gL_ControlLegacy1.MainDrawable = null;
this.gL_ControlLegacy1.Name = "gL_ControlLegacy1";
this.gL_ControlLegacy1.ShowOrientationCube = false;
this.gL_ControlLegacy1.Size = new System.Drawing.Size(278, 182);
this.gL_ControlLegacy1.Stereoscopy = true;
this.gL_ControlLegacy1.TabIndex = 2;
this.gL_ControlLegacy1.VSync = false;
this.gL_ControlLegacy1.ZFar = 1000F;
this.gL_ControlLegacy1.ZNear = 0.01F;
//
// gL_ControlModern1
//
this.gL_ControlModern1.ActiveCamera = null;
this.gL_ControlModern1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.gL_ControlModern1.BackColor = System.Drawing.Color.Black;
this.gL_ControlModern1.CameraDistance = -10F;
this.gL_ControlModern1.CameraTarget = ((OpenTK.Vector3)(resources.GetObject("gL_ControlModern1.CameraTarget")));
this.gL_ControlModern1.CamRotX = 0F;
this.gL_ControlModern1.CamRotY = 0F;
this.gL_ControlModern1.CurrentShader = null;
this.gL_ControlModern1.DragStartPos = new System.Drawing.Point(0, 0);
this.gL_ControlModern1.Fov = 0.7853982F;
this.gL_ControlModern1.GradientBackground = true;
this.gL_ControlModern1.Location = new System.Drawing.Point(297, 20);
this.gL_ControlModern1.MainDrawable = null;
this.gL_ControlModern1.Name = "gL_ControlModern1";
this.gL_ControlModern1.ShowOrientationCube = true;
this.gL_ControlModern1.Size = new System.Drawing.Size(689, 715);
this.gL_ControlModern1.Stereoscopy = false;
this.gL_ControlModern1.TabIndex = 1;
this.gL_ControlModern1.VSync = false;
this.gL_ControlModern1.ZFar = 1000F;
this.gL_ControlModern1.ZNear = 0.01F;
//
// TestingForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(998, 747);
this.Controls.Add(this.listBox1);
this.Controls.Add(this.button1);
this.Controls.Add(this.gL_ControlLegacy1);
this.Controls.Add(this.gL_ControlModern1);
this.Name = "TestingForm";
this.Text = "Testing";
this.ResumeLayout(false);
}
#endregion
private GL_EditorFramework.GL_Core.GL_ControlModern gL_ControlModern1;
private GL_EditorFramework.GL_Core.GL_ControlLegacy gL_ControlLegacy1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.ListBox listBox1;
}
}

View file

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using GL_EditorFramework.EditorDrawables;
using OpenTK;
namespace Testing
{
public partial class TestingForm : Form
{
public TestingForm()
{
InitializeComponent();
}
private EditorScene scene;
private Random rng = new Random();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
scene = new EditorScene();
listBox1.Items.Add("moving platform");
scene.objects.Add(new AnimatedObject(new Vector3(0, -4, 0)));
for (int i = 0; i<5; i++)
{
listBox1.Items.Add("block");
scene.objects.Add(new SingleObject(new Vector3(i,0,0)));
}
gL_ControlModern1.MainDrawable = scene;
gL_ControlModern1.ActiveCamera = new GL_EditorFramework.StandardCameras.InspectCamera(1f);
gL_ControlLegacy1.MainDrawable = new SingleObject(new Vector3());
scene.SelectionChanged += Scene_SelectionChanged;
listBox1.SelectedIndexChanged += ListBox1_SelectedIndexChanged;
}
private void Scene_SelectionChanged(object sender, EventArgs e)
{
listBox1.SelectedIndexChanged -= ListBox1_SelectedIndexChanged;
listBox1.SelectedIndices.Clear();
int i = 0;
foreach(EditableObject o in scene.objects)
{
if(o.IsSelected())
listBox1.SelectedIndices.Add(i);
i++;
}
listBox1.SelectedIndexChanged += ListBox1_SelectedIndexChanged;
}
private void ListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
List<EditableObject> newSelection = new List<EditableObject>();
foreach(int i in listBox1.SelectedIndices)
{
newSelection.Add(scene.objects[i]);
}
scene.SelectedObjects = newSelection;
}
private void button1_Click(object sender, EventArgs e)
{
Color rand = Color.FromArgb(rng.Next());
listBox1.Items.Add("block"); //make sure to add the entry before you add an object because the SelectionChanged event will be fired
scene.Add(new SingleObject(new Vector3()));
}
}
}

View file

@ -0,0 +1,134 @@
<?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>
<data name="gL_ControlLegacy1.CameraTarget" mimetype="application/x-microsoft.net.object.binary.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAElPcGVuVEssIFZlcnNpb249My4wLjEuMCwgQ3VsdHVyZT1uZXV0
cmFsLCBQdWJsaWNLZXlUb2tlbj1iYWQxOTlmZTg0ZWIzZGY0BQEAAAAOT3BlblRLLlZlY3RvcjMDAAAA
AVgBWQFaAAAACwsLAgAAAAAAAAAAAAAAAAAAAAs=
</value>
</data>
<data name="gL_ControlModern1.CameraTarget" mimetype="application/x-microsoft.net.object.binary.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAElPcGVuVEssIFZlcnNpb249My4wLjEuMCwgQ3VsdHVyZT1uZXV0
cmFsLCBQdWJsaWNLZXlUb2tlbj1iYWQxOTlmZTg0ZWIzZGY0BQEAAAAOT3BlblRLLlZlY3RvcjMDAAAA
AVgBWQFaAAAACwsLAgAAAAAAAAAAAAAAAAAAAAs=
</value>
</data>
</root>

View file

@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Xml;
using System.Drawing;
using System.IO;
using Switch_Toolbox.Library;
namespace FirstPlugin
{
//Based on
// https://github.com/jam1garner/Smash-Forge/blob/26e0dcbd84cdf8a4ffe3fbe0b0317520a4099286/Smash%20Forge/Filetypes/Application/Config.cs
class Config
{
public static void StartupFromFile(string fileName)
{
if (!File.Exists(fileName))
{
Save();
return;
}
ReadConfigFromFile(fileName);
}
private static void ReadConfigFromFile(string fileName)
{
int discordImageKey;
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
Queue<XmlNode> que = new Queue<XmlNode>();
foreach (XmlNode node in doc.ChildNodes)
que.Enqueue(node);
while (que.Count > 0)
{
XmlNode node = que.Dequeue();
foreach (XmlNode n in node.ChildNodes)
que.Enqueue(n);
switch (node.Name)
{
case "ExternalFMATPath":
if (node.ParentNode != null && node.ParentNode.Name.Equals("PATHSETTINGS"))
if (File.Exists(node.InnerText))
PluginRuntime.ExternalFMATPath = node.InnerText;
break;
case "MarioOdysseyGamePath":
if (node.ParentNode != null && node.ParentNode.Name.Equals("PATHSETTINGS"))
if (File.Exists(node.InnerText))
PluginRuntime.OdysseyGamePath = node.InnerText;
break;
}
}
}
public static void Save()
{
XmlDocument doc = CreateXmlFromSettings();
doc.Save("Lib/Plugins/config.xml");
}
private static XmlDocument CreateXmlFromSettings()
{
XmlDocument doc = new XmlDocument();
XmlNode mainNode = doc.CreateElement("FORGECONFIG");
doc.AppendChild(mainNode);
AppendDOCKSettings(doc, mainNode);
AppendPathSettings(doc, mainNode);
return doc;
}
private static void AppendPathSettings(XmlDocument doc, XmlNode parentNode)
{
XmlNode pathSettingsNode = doc.CreateElement("PATHSETTINGS");
parentNode.AppendChild(pathSettingsNode);
pathSettingsNode.AppendChild(createNode(doc, "ExternalFMATPath", PluginRuntime.ExternalFMATPath));
pathSettingsNode.AppendChild(createNode(doc, "MarioOdysseyGamePath", PluginRuntime.OdysseyGamePath));
}
private static void AppendDOCKSettings(XmlDocument doc, XmlNode parentNode)
{
XmlNode renderSettingsNode = doc.CreateElement("DOCKSETTINGS");
parentNode.AppendChild(renderSettingsNode);
}
public static XmlNode createNode(XmlDocument doc, string el, string v)
{
XmlNode floorstyle = doc.CreateElement(el);
floorstyle.InnerText = v;
return floorstyle;
}
}
}

Binary file not shown.

View file

@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.IO;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library.Forms;
using System.Windows.Forms;
using aampv1 = AampV1Library;
using aampv2 = AampV2Library;
using FirstPlugin.Forms;
namespace FirstPlugin
{
public class AAMP : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "AAMP" };
public string[] Extension { get; set; } = new string[] { "*.aamp" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(Stream stream)
{
using (var reader = new FileReader(stream, true))
{
return reader.CheckSignature(4, "AAMP");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public override void OnClick(TreeView treeview)
{
}
private uint CheckVersion(Stream stream)
{
using (FileReader reader = new FileReader(stream, true))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
reader.ReadSignature(4, "AAMP");
reader.Position = 4;
return reader.ReadUInt32();
}
}
aampv1.AampFile aampFileV1;
aampv2.AampFile aampFileV2;
AampV1Editor aampEditorV1;
AampV2Editor aampEditorV2;
public void Load(Stream stream)
{
CanSave = true;
Text = FileName;
uint Version = CheckVersion(stream);
if (Version == 1)
{
aampFileV1 = new aampv1.AampFile(stream);
Text = $"{FileName} Type [{aampFileV1.EffectType}]";
aampEditorV1 = new AampV1Editor();
aampEditorV1.LoadFile(aampFileV1, this);
}
else if (Version == 2)
{
aampFileV2 = new aampv2.AampFile(stream);
Text = $"{FileName} Type [{aampFileV2.EffectType}]";
aampEditorV2 = new AampV2Editor();
aampEditorV2.LoadFile(aampFileV2, this);
}
else
{
throw new Exception($"Unsupported AAMP version! {Version}");
}
}
public override void OnAfterAdded()
{
if (aampEditorV1 != null)
{
aampEditorV1.LoadImages(TreeView, this);
}
if (aampEditorV2 != null)
{
aampEditorV2.LoadImages(TreeView, this);
}
}
public void Unload()
{
}
public byte[] Save()
{
var mem = new MemoryStream();
if (aampFileV1 != null)
aampFileV1.Save(mem);
else
aampFileV2.Save(mem);
return mem.ToArray();
}
}
}

View file

@ -0,0 +1,552 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using System.IO;
using BezelEngineArchive_Lib;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library.Forms;
namespace FirstPlugin
{
public class BEA : TreeNode, IArchiveFile
{
public bool CanAddFiles { get; set; } = false;
public bool CanRenameFiles { get; set; } = false;
public bool CanDeleteFiles { get; set; } = false;
public bool CanReplaceFiles { get; set; } = true;
public IEnumerable<ArchiveFileInfo> Files { get; }
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Bevel Engine Archive" };
public string[] Extension { get; set; } = new string[] { "*.bea" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(Stream stream)
{
using (var reader = new FileReader(stream, true))
{
return reader.CheckSignature(4, "SCNE");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
types.Add(typeof(MenuExt));
return types.ToArray();
}
}
class MenuExt : IFileMenuExtension
{
public STToolStripItem[] NewFileMenuExtensions => null;
public STToolStripItem[] NewFromFileMenuExtensions => null;
public STToolStripItem[] ToolsMenuExtensions => null;
public STToolStripItem[] TitleBarExtensions => null;
public STToolStripItem[] CompressionMenuExtensions => null;
public STToolStripItem[] ExperimentalMenuExtensions => experimentalMenu;
STToolStripItem[] experimentalMenu = new STToolStripItem[1];
public MenuExt()
{
experimentalMenu[0] = new STToolStripItem("BEA");
STToolStripItem batchLUA = new STToolStripItem("Batch Extract LUA");
batchLUA.Click += BatchExtractLUA;
experimentalMenu[0].DropDownItems.Add(batchLUA);
}
private void BatchExtractLUA(object sender, EventArgs e)
{
FolderSelectDialog ofd = new FolderSelectDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
string folderPath = ofd.SelectedPath;
foreach (string file in Directory.GetFiles(folderPath))
{
Console.WriteLine(file);
if (Path.GetExtension(file) == ".bea")
{
BEA bea = new BEA();
bea.FileName = file;
bea.Load(new FileStream(file, FileMode.Open));
foreach (FileEntry asset in bea.Nodes)
{
if (Path.GetExtension(asset.FullName) == ".lua")
{
try
{
if (!String.IsNullOrWhiteSpace(Path.GetDirectoryName($"{folderPath}/{bea.Name}/{asset.FullName}")))
{
if (!File.Exists(asset.FullName))
{
if (!Directory.Exists($"{folderPath}/{bea.Name}/{asset.FullName}"))
{
Directory.CreateDirectory(Path.GetDirectoryName($"{folderPath}/{bea.Name}/{asset.FullName}"));
}
}
}
File.WriteAllBytes($"{folderPath}/{bea.Name}/{asset.FullName}", GetASSTData(asset));
}
catch
{
}
}
}
}
}
}
}
}
public BezelEngineArchive beaFile;
static STProgressBar progressBar;
public void Load(System.IO.Stream stream)
{
Text = FileName;
CanSave = true;
BezelEngineArchive bea = new BezelEngineArchive(stream);
// FillTreeNodes(this, beaFile.FileList);
ContextMenu = new ContextMenu();
MenuItem save = new MenuItem("Save");
ContextMenu.MenuItems.Add(save);
save.Click += Save;
MenuItem previewFiles = new MenuItem("Preview Window");
ContextMenu.MenuItems.Add(previewFiles);
previewFiles.Click += PreviewWindow;
MenuItem exportAll = new MenuItem("Export All");
ContextMenu.MenuItems.Add(exportAll);
exportAll.Click += ExportAll;
}
public void Unload()
{
}
public bool AddFile(ArchiveFileInfo archiveFileInfo)
{
return false;
}
public bool DeleteFile(ArchiveFileInfo archiveFileInfo)
{
return false;
}
IEnumerable<TreeNode> Collect(TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
yield return node;
foreach (var child in Collect(node.Nodes))
yield return child;
}
}
private void Save(object sender, EventArgs args)
{
Cursor.Current = Cursors.WaitCursor;
List<IFileFormat> formats = new List<IFileFormat>();
formats.Add(this);
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = Utils.GetAllFilters(formats);
sfd.FileName = FileName;
if (sfd.ShowDialog() == DialogResult.OK)
{
STFileSaver.SaveFileFormat(this, sfd.FileName);
}
GC.Collect();
}
public byte[] Save()
{
beaFile.FileList.Clear();
beaFile.FileDictionary.Clear();
foreach (TreeNode node in Collect(Nodes))
{
if (node is TreeNodeFile && node != this)
{
IFileFormat fileFormat = (IFileFormat)node;
if (fileFormat != null && fileFormat.CanSave)
{
byte[] uncomrompressedData = new byte[0];
//Save any active files in the editor if supported
if (fileFormat.CanSave)
uncomrompressedData = fileFormat.Save();
//Create a new asset entry
ASST asset = new ASST();
asset.unk = 2;
asset.unk2 = 2;
asset.UncompressedSize = uncomrompressedData.LongLength;
if (fileFormat.IFileInfo.FileIsCompressed)
asset.FileData = STLibraryCompression.ZSTD.Compress(uncomrompressedData);
else
asset.FileData = uncomrompressedData;
asset.FileName = fileFormat.FilePath;
beaFile.FileList.Add(fileFormat.FilePath, asset);
beaFile.FileDictionary.Add(fileFormat.FilePath);
}
}
else if (node is FileEntry)
{
ASST asset = new ASST();
asset.unk = ((FileEntry)node).unk1;
asset.unk2 = ((FileEntry)node).unk2;
asset.FileName = ((FileEntry)node).FullName;
asset.FileData = ((FileEntry)node).data;
byte[] uncomp = GetASSTData((FileEntry)node);
asset.UncompressedSize = uncomp.Length;
beaFile.FileList.Add(asset.FileName, asset);
beaFile.FileDictionary.Add(asset.FileName);
}
}
MemoryStream mem = new MemoryStream();
beaFile.Save(mem);
return mem.ToArray();
}
private void ExportAll(object sender, EventArgs args)
{
FolderSelectDialog fsd = new FolderSelectDialog();
if (fsd.ShowDialog() == DialogResult.OK)
{
progressBar = new STProgressBar();
progressBar.Task = "Extracing Files...";
progressBar.Refresh();
progressBar.Value = 0;
progressBar.StartPosition = FormStartPosition.CenterScreen;
progressBar.Show();
ExportAll(fsd.SelectedPath, progressBar);
}
}
private void ExportAll(string Folder, STProgressBar progressBar)
{
int Curfile = 0;
foreach (FileEntry asst in Nodes)
{
int value = (Curfile * 100) / beaFile.FileList.Count;
progressBar.Value = value;
progressBar.Refresh();
try
{
if (!String.IsNullOrWhiteSpace(Path.GetDirectoryName($"{Folder}/{beaFile.Name}/{asst.FullName}")))
{
if (!File.Exists(asst.FullName))
{
if (!Directory.Exists($"{Folder}/{beaFile.Name}/{asst.FullName}"))
{
Directory.CreateDirectory(Path.GetDirectoryName($"{Folder}/{beaFile.Name}/{asst.FullName}"));
}
}
}
File.WriteAllBytes($"{Folder}/{beaFile.Name}/{asst.FullName}", GetASSTData(asst));
}
catch
{
}
Curfile++;
if (value == 99)
value = 100;
progressBar.Value = value;
progressBar.Refresh();
}
}
private void CallRecursive(TreeView treeView)
{
// Print each node recursively.
TreeNodeCollection nodes = treeView.Nodes;
foreach (TreeNode n in nodes)
{
PrintRecursive(n);
}
}
private void PrintRecursive(TreeNode treeNode)
{
// Print each node recursively.
foreach (TreeNode tn in treeNode.Nodes)
{
PrintRecursive(tn);
}
}
public void PreviewWindow(object sender, EventArgs args)
{
PreviewFormatList previewFormatList = new PreviewFormatList();
if (previewFormatList.ShowDialog() == DialogResult.OK)
{
CallRecursive(TreeView);
Console.WriteLine("Loaded files");
Console.WriteLine(PluginRuntime.bntxContainers.Count);
PreviewEditor previewWindow = new PreviewEditor();
previewWindow.Show();
}
}
public bool Compressed;
public class FolderEntry : TreeNode
{
public FolderEntry()
{
ImageKey = "folder";
SelectedImageKey = "folder";
}
public FolderEntry(string Name)
{
Text = Name;
}
}
public class FileEntry : TreeNodeCustom
{
public FileEntry()
{
ImageKey = "fileBlank";
SelectedImageKey = "fileBlank";
ContextMenu = new ContextMenu();
MenuItem export = new MenuItem("Export");
ContextMenu.MenuItems.Add(export);
export.Click += Export;
MenuItem replace = new MenuItem("Replace");
ContextMenu.MenuItems.Add(replace);
replace.Click += Replace;
}
public string FullName;
public IFileFormat FileHandle; //Load file instance to save later if possible
public byte[] data;
public ushort unk1;
public ushort unk2;
public bool IsCompressed;
private void Export(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = Text;
sfd.DefaultExt = Path.GetExtension(Text);
sfd.Filter = "All files(*.*)|*.*";
if (sfd.ShowDialog() == DialogResult.OK)
{
File.WriteAllBytes(sfd.FileName, GetASSTData(this));
}
}
private void Replace(object sender, EventArgs args)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.FileName = Text;
ofd.DefaultExt = Path.GetExtension(Text);
ofd.Filter = "All files(*.*)|*.*";
if (ofd.ShowDialog() == DialogResult.OK)
{
SetASST(this, File.ReadAllBytes(ofd.FileName));
}
}
public override void OnDoubleMouseClick(TreeView treeview)
{
if (GetASSTData(this) != null)
{
TreeNode node = STFileLoader.GetNodeFileFormat(FullName, GetASSTData(this), true, this, true, IsCompressed, CompressionType.Zstb);
if (node != null)
ReplaceNode(this.Parent, this, node);
}
}
}
public static void ReplaceNode(TreeNode node, TreeNode replaceNode, TreeNode NewNode)
{
int index = node.Nodes.IndexOf(replaceNode);
node.Nodes.RemoveAt(index);
node.Nodes.Insert(index, NewNode);
}
public static byte[] GetASSTData(FileEntry entry)
{
if (entry.IsCompressed)
return STLibraryCompression.ZSTD.Decompress(entry.data);
else
return entry.data;
}
public static void SetASST(FileEntry fileEntry, byte[] data)
{
if (fileEntry.IsCompressed)
fileEntry.data = STLibraryCompression.ZSTD.Compress(data);
else
fileEntry.data = data;
}
void FillTreeNodes(TreeNode root, Dictionary<string, ASST> files)
{
var rootText = root.Text;
var rootTextLength = rootText.Length;
var nodeStrings = files;
foreach (var node in nodeStrings)
{
string nodeString = node.Key;
var roots = nodeString.Split(new char[] { '/' },
StringSplitOptions.RemoveEmptyEntries);
// The initial parent is the root node
TreeNode parentNode = root;
var sb = new StringBuilder(rootText, nodeString.Length + rootTextLength);
for (int rootIndex = 0; rootIndex < roots.Length; rootIndex++)
{
// Build the node name
var parentName = roots[rootIndex];
sb.Append("/");
sb.Append(parentName);
var nodeName = sb.ToString();
// Search for the node
var index = parentNode.Nodes.IndexOfKey(nodeName);
if (index == -1)
{
// Node was not found, add it
var temp = new TreeNode(parentName, 0, 0);
if (rootIndex == roots.Length - 1)
temp = SetupFileEntry(node.Value,parentName, node.Value.FileName, node.Value.IsCompressed);
else
temp = SetupFolderEntry(temp);
temp.Name = nodeName;
parentNode.Nodes.Add(temp);
parentNode = temp;
}
else
{
// Node was found, set that as parent and continue
parentNode = parentNode.Nodes[index];
}
}
}
}
public FolderEntry SetupFolderEntry(TreeNode node)
{
FolderEntry folder = new FolderEntry();
folder.Text = node.Text;
return folder;
}
List<string> BuildFinalList(List<string> paths)
{
var finalList = new List<string>();
foreach (var path in paths)
{
bool found = false;
foreach (var item in finalList)
{
if (item.StartsWith(path, StringComparison.Ordinal))
{
found = true;
break;
}
}
if (!found)
{
finalList.Add(path);
}
}
return finalList;
}
public FileEntry SetupFileEntry(ASST asset,string name, string fullName, bool IsCompressed)
{
FileEntry fileEntry = new FileEntry();
fileEntry.FullName = fullName;
fileEntry.Name = name;
fileEntry.Text = name;
fileEntry.unk1 = asset.unk;
fileEntry.unk2 = asset.unk2;
fileEntry.IsCompressed = IsCompressed;
// fileEntry.data = asset.FileData;
//Now check magic
//Todo clean this part up
byte[] data = asset.FileData;
if (IsCompressed)
{
try
{
data = STLibraryCompression.ZSTD.Decompress(asset.FileData);
}
catch
{
Console.WriteLine("Unkwon compression for file " + fileEntry.Name);
}
}
string ext = Path.GetExtension(name);
string SarcEx = SARCExt.SARC.GuessFileExtension(data);
if (name.EndsWith("bfres") || name.EndsWith("fmdb") || name.EndsWith("fskb") ||
name.EndsWith("ftsb") || name.EndsWith("fvmb") || name.EndsWith("fvbb") ||
name.EndsWith("fspb") || name.EndsWith("fsnb"))
{
fileEntry.ImageKey = "bfres";
fileEntry.SelectedImageKey = "bfres";
}
if (SarcEx == ".bntx")
{
fileEntry.ImageKey = "bntx";
fileEntry.SelectedImageKey = "bntx";
}
if (SarcEx == ".byaml")
{
fileEntry.ImageKey = "byaml";
fileEntry.SelectedImageKey = "byaml";
}
if (SarcEx == ".aamp")
{
fileEntry.ImageKey = "aamp";
fileEntry.SelectedImageKey = "aamp";
}
if (ext == ".lua")
{
}
data = new byte[0];
return fileEntry;
}
}
}

View file

@ -0,0 +1,400 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using System.IO;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library.Forms;
namespace FirstPlugin
{
public class GFPAK : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Graphic Package" };
public string[] Extension { get; set; } = new string[] { "*.gfpak" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(8, "GFLXPACK");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public void Load(System.IO.Stream stream)
{
CanSave = true;
Read(new FileReader(stream));
Text = FileName;
ContextMenu = new ContextMenu();
MenuItem save = new MenuItem("Save");
ContextMenu.MenuItems.Add(save);
save.Click += Save;
MenuItem previewFiles = new MenuItem("Preview Window");
ContextMenu.MenuItems.Add(previewFiles);
previewFiles.Click += PreviewWindow;
}
public void Unload()
{
}
public byte[] Save()
{
MemoryStream mem = new MemoryStream();
Write(new FileWriter(mem));
return mem.ToArray();
}
private void Save(object sender, EventArgs args)
{
List<IFileFormat> formats = new List<IFileFormat>();
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = Utils.GetAllFilters(formats);
sfd.FileName = FileName;
if (sfd.ShowDialog() == DialogResult.OK)
{
STFileSaver.SaveFileFormat(this, sfd.FileName);
}
}
private void PreviewWindow(object sender, EventArgs args)
{
PreviewFormatList previewFormatList = new PreviewFormatList();
if (previewFormatList.ShowDialog() == DialogResult.OK)
{
CallRecursive(TreeView);
PreviewEditor previewWindow = new PreviewEditor();
previewWindow.Show();
}
}
private void CallRecursive(TreeView treeView)
{
// Print each node recursively.
TreeNodeCollection nodes = treeView.Nodes;
foreach (TreeNode n in nodes)
{
PrintRecursive(n);
}
}
private void PrintRecursive(TreeNode treeNode)
{
// Print each node recursively.
foreach (TreeNode tn in treeNode.Nodes)
{
PrintRecursive(tn);
}
}
public ushort BOM;
public uint Version;
public List<FileEntry> files = new List<FileEntry>();
public List<Folder> folders = new List<Folder>();
public List<UInt64> hashes = new List<UInt64>();
public List<HashIndex> hashIndices = new List<HashIndex>();
public int version;
public int FolderCount;
public void Read(FileReader reader)
{
string Signature = reader.ReadString(8, Encoding.ASCII);
if (Signature != "GFLXPACK")
throw new Exception($"Invalid signature {Signature}! Expected GFLXPACK.");
version = reader.ReadInt32();
uint padding = reader.ReadUInt32();
uint FileCount = reader.ReadUInt32();
FolderCount = reader.ReadInt32();
ulong FileInfoOffset = reader.ReadUInt64();
ulong hashArrayPathsOffset = reader.ReadUInt64();
ulong FolderArrayOffset = reader.ReadUInt64();
reader.Seek((long)FolderArrayOffset, SeekOrigin.Begin);
for (int i = 0; i < FolderCount; i++)
{
Folder folder = new Folder();
folder.Read(reader);
folders.Add(folder);
}
reader.Seek((long)hashArrayPathsOffset, SeekOrigin.Begin);
for (int i = 0; i < FileCount; i++)
{
ulong hash = reader.ReadUInt64();
hashes.Add(hash);
}
reader.Seek((long)FileInfoOffset, SeekOrigin.Begin);
for (int i = 0; i < FileCount; i++)
{
FileEntry fileEntry = new FileEntry();
fileEntry.Read(reader);
fileEntry.Text = hashes[i].ToString();
Nodes.Add(fileEntry);
files.Add(fileEntry);
}
reader.Close();
reader.Dispose();
}
public void Write(FileWriter writer)
{
writer.WriteSignature("GFLXPACK");
writer.Write(version);
writer.Write(0);
writer.Write(files.Count);
writer.Write(FolderCount);
long FileInfoOffset = writer.Position;
writer.Write(0L);
long HashArrayOffset = writer.Position;
writer.Write(0L);
long folderArrOffset = writer.Position;
//Reserve space for folder offsets
for (int f = 0; f < FolderCount; f++)
writer.Write(0L);
//Now write all sections
writer.WriteUint64Offset(HashArrayOffset);
writer.Write(hashes);
//Save folder sections
List<long> FolderSectionPositions = new List<long>();
foreach (var folder in folders)
{
FolderSectionPositions.Add(writer.Position);
folder.Write(writer);
}
//Write the folder offsets back
using (writer.TemporarySeek(folderArrOffset, SeekOrigin.Begin))
{
foreach (long offset in FolderSectionPositions)
writer.Write(offset);
}
//Now file data
writer.WriteUint64Offset(FileInfoOffset);
foreach (var fileTbl in files)
fileTbl.Write(writer);
//Save data blocks
foreach (var fileTbl in files)
{
fileTbl.WriteBlock(writer);
}
writer.Align(16);
}
public class Folder
{
public ulong hash;
public uint FileCount;
public uint unknown;
public List<HashIndex> hashes = new List<HashIndex>();
public void Read(FileReader reader)
{
hash = reader.ReadUInt64();
FileCount = reader.ReadUInt32();
unknown = reader.ReadUInt32();
for (int f = 0; f < FileCount; f++)
{
HashIndex hash = new HashIndex();
hash.Read(reader);
hashes.Add(hash);
}
}
public void Write(FileWriter writer)
{
writer.Write(hash);
writer.Write(FileCount);
writer.Write(unknown);
foreach (var hash in hashes)
hash.Write(writer);
}
}
public class HashIndex
{
public ulong hash;
public int Index;
public uint unknown;
public void Read(FileReader reader)
{
hash = reader.ReadUInt64();
Index = reader.ReadInt32();
unknown = reader.ReadUInt32(); //Always 0xCC?
}
public void Write(FileWriter writer)
{
writer.Write(hash);
writer.Write(Index);
writer.Write(unknown);
}
}
public class FileEntry : TreeNodeCustom
{
public FileEntry()
{
ImageKey = "fileBlank";
SelectedImageKey = "fileBlank";
ContextMenu = new ContextMenu();
MenuItem export = new MenuItem("Export");
ContextMenu.MenuItems.Add(export);
export.Click += Export;
}
public uint unkown;
public uint CompressionType;
public byte[] data;
private long DataOffset;
public IFileFormat FileHandler;
public uint CompressedFileSize;
public uint padding;
public void Read(FileReader reader)
{
unkown = reader.ReadUInt16(); //Usually 9?
CompressionType = reader.ReadUInt16();
uint DecompressedFileSize = reader.ReadUInt32();
CompressedFileSize = reader.ReadUInt32();
padding = reader.ReadUInt32();
ulong FileOffset = reader.ReadUInt64();
using (reader.TemporarySeek((long)FileOffset, SeekOrigin.Begin))
{
data = reader.ReadBytes((int)CompressedFileSize);
data = STLibraryCompression.Type_LZ4.Decompress(data, 0, (int)CompressedFileSize, (int)DecompressedFileSize);
string ext = SARCExt.SARC.GuessFileExtension(data);
if (ext == ".bntx")
{
ImageKey = "bntx";
SelectedImageKey = "bntx";
}
if (ext == ".byaml")
{
ImageKey = "byaml";
SelectedImageKey = "byaml";
}
if (ext == ".aamp")
{
ImageKey = "aamp";
SelectedImageKey = "aamp";
}
if (ext == ".lua")
{
}
}
}
byte[] CompressedData;
public void Write(FileWriter writer)
{
if (FileHandler != null && FileHandler.CanSave)
{
data = FileHandler.Save();
}
CompressedData = Compress(data, CompressionType);
writer.Write((ushort)unkown);
writer.Write((ushort)CompressionType);
writer.Write(data.Length);
writer.Write(CompressedData.Length);
writer.Write(padding);
DataOffset = writer.Position;
writer.Write(0L);
}
public void WriteBlock(FileWriter writer)
{
writer.Align(16);
writer.WriteUint64Offset(DataOffset);
writer.Write(CompressedData);
}
public static byte[] Compress(byte[] data, uint Type)
{
if (Type == 2)
{
return STLibraryCompression.Type_LZ4.Compress(data);
}
else
throw new Exception("Unkown compression type?");
}
public override void OnClick(TreeView treeView)
{
HexEditor editor = (HexEditor)LibraryGUI.Instance.GetActiveContent(typeof(HexEditor));
if (editor == null)
{
editor = new HexEditor();
LibraryGUI.Instance.LoadEditor(editor);
}
editor.Text = Text;
editor.Dock = DockStyle.Fill;
editor.LoadData(data);
}
public override void OnDoubleMouseClick(TreeView treeView)
{
FileHandler = STFileLoader.OpenFileFormat(Name, data,false, true, this);
if (FileHandler != null && FileHandler is TreeNode)
ReplaceNode(this.Parent, this, (TreeNode)FileHandler);
}
private void Export(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = Text;
sfd.Filter = "All files(*.*)|*.*";
if (sfd.ShowDialog() == DialogResult.OK)
{
File.WriteAllBytes(sfd.FileName, data);
}
}
}
public static void ReplaceNode(TreeNode node, TreeNode replaceNode, TreeNode NewNode)
{
if (NewNode == null)
return;
int index = node.Nodes.IndexOf(replaceNode);
node.Nodes.RemoveAt(index);
node.Nodes.Insert(index, NewNode);
}
}
}

View file

@ -0,0 +1,409 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library.Forms;
using System.Windows.Forms;
namespace FirstPlugin
{
class NARC : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Nitro Archive (NARC)" };
public string[] Extension { get; set; } = new string[] { "*.narc" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "NARC");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public class FileEntry : TreeNodeCustom
{
public byte[] FileData { get; set; }
public NARC.FileAllocationEntry entry;
public FileImageBlock fileImage;
public FileEntry(string Name)
{
Text = Name;
if (Utils.HasExtension(Name, ".cbfmd") ||
Utils.HasExtension(Name, ".cbfa") ||
Utils.HasExtension(Name, ".cbfsa"))
{
ImageKey = "bfres";
SelectedImageKey = "bfres";
}
if (Utils.HasExtension(Name, ".cbntx"))
{
ImageKey = "bntx";
SelectedImageKey = "bntx";
}
ContextMenu = new ContextMenu();
ContextMenu.MenuItems.Add(new MenuItem("Export Raw Data", Export));
}
private void Export(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = Text;
if (sfd.ShowDialog() == DialogResult.OK)
{
System.IO.File.WriteAllBytes(sfd.FileName, DecompressBlock());
}
}
public override void OnDoubleMouseClick(TreeView treeView)
{
TreeNode node = STFileLoader.GetNodeFileFormat(Text, DecompressBlock(), true, this);
if (node != null)
ReplaceNode(this.Parent, this, node);
}
public static void ReplaceNode(TreeNode node, TreeNode replaceNode, TreeNode NewNode)
{
if (NewNode == null)
return;
int index = node.Nodes.IndexOf(replaceNode);
node.Nodes.RemoveAt(index);
node.Nodes.Insert(index, NewNode);
}
public override void OnClick(TreeView treeView)
{
HexEditor editor = (HexEditor)LibraryGUI.Instance.GetActiveContent(typeof(HexEditor));
if (editor == null)
{
editor = new HexEditor();
LibraryGUI.Instance.LoadEditor(editor);
}
editor.Text = Text;
editor.Dock = DockStyle.Fill;
editor.LoadData(DecompressBlock());
}
public byte[] DecompressBlock()
{
byte[] data = GetBlock();
var reader = new FileReader(data);
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
byte compType = reader.ReadByte();
if (compType == 0x50)
{
reader.Seek(4, System.IO.SeekOrigin.Begin);
uint decompSize = reader.ReadUInt32();
uint compSize = (uint)reader.BaseStream.Length - 8;
byte[] filedata = reader.getSection(8, (int)compSize);
// data = STLibraryCompression.Type_LZ4.Decompress(filedata, 0, (int)compSize, (int)decompSize);
// data = STLibraryCompression.GZIP.Decompress(filedata);
return data;
}
else if (compType == 0x30)
{
uint decompSize = reader.ReadUInt32();
uint compSize = (uint)reader.BaseStream.Length;
compSize -= 16;
byte[] filedata = reader.getSection(16, (int)compSize);
reader.Close();
reader.Dispose();
data = STLibraryCompression.ZLIB.Decompress(filedata, decompSize);
}
return data;
}
public byte[] GetBlock()
{
return Utils.SubArray(fileImage.dataBlock, entry.StartOffset, entry.EndOffset);
}
}
Header header;
public List<FileEntry> FileEntries = new List<FileEntry>();
public void Load(System.IO.Stream stream)
{
Text = FileName;
header = new Header(new FileReader(stream));
var names = GetNames(header.FNTB);
List<byte> Data = new List<byte>();
for (ushort i = 0; i < header.FATB.FileCount; i++)
{
FileEntries.Add(new FileEntry(names[i])
{
entry = header.FATB.FileEntries[i],
fileImage = header.FIMG,
});
Nodes.Add(FileEntries[i]);
}
}
public List<string> GetNames(FileNameTable nameTable)
{
var names = new List<string>();
foreach (var tblEntry in nameTable.entryNameTable)
{
if (tblEntry is EntryNameTableFileEntry)
names.Add(((EntryNameTableFileEntry)tblEntry).entryName);
}
return names;
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
//EFE for REing format https://github.com/Gericom/EveryFileExplorer/blob/f9f00d193c9608d71c9a23d9f3ab7e752f4ada2a/NDS/NitroSystem/FND/NARC.cs
public class Header
{
public string Signature;
public ushort ByteOrder;
public uint FileSize;
public uint Version;
public ushort HeaderSize;
public ushort DataBlocks;
public FileAllocationTableBlock FATB;
public FileNameTable FNTB;
public FileImageBlock FIMG;
public Header(FileReader reader)
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
reader.ReadSignature(4, "NARC");
ByteOrder = reader.ReadUInt16();
reader.CheckByteOrderMark(ByteOrder);
Version = reader.ReadUInt16();
FileSize = reader.ReadUInt32();
HeaderSize = reader.ReadUInt16();
DataBlocks = reader.ReadUInt16();
FATB = new FileAllocationTableBlock(reader);
FNTB = new FileNameTable(reader);
FIMG = new FileImageBlock(reader);
}
public void Write(FileWriter writer)
{
writer.WriteSignature(Signature);
writer.Write(ByteOrder);
writer.Write(Version);
writer.Write(FileSize);
writer.Write(HeaderSize);
writer.Write(DataBlocks);
}
}
public class FileAllocationTableBlock
{
public string Signature;
public uint Size;
public ushort FileCount;
public ushort Reserved;
public List<FileAllocationEntry> FileEntries = new List<FileAllocationEntry>();
public FileAllocationTableBlock(FileReader reader)
{
long startPos = reader.Position;
reader.ReadSignature(4, "BTAF");
Size = reader.ReadUInt32();
FileCount = reader.ReadUInt16();
Reserved = reader.ReadUInt16();
for (int i = 0; i < FileCount; i++)
FileEntries.Add(new FileAllocationEntry(reader));
reader.Seek(startPos + Size, System.IO.SeekOrigin.Begin);
}
}
public class FileAllocationEntry
{
public uint StartOffset;
public uint EndOffset;
public FileAllocationEntry(FileReader reader)
{
StartOffset = reader.ReadUInt32();
EndOffset = reader.ReadUInt32();
}
public void Write(FileWriter writer)
{
writer.Write(StartOffset);
writer.Write(EndOffset);
}
}
public class FileImageBlock
{
public string Signature;
public uint Size;
public byte[] dataBlock;
public FileImageBlock(FileReader reader)
{
reader.ReadSignature(4, "GMIF");
Size = reader.ReadUInt32();
dataBlock = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
}
}
public class FileNameTable
{
public string Signature;
public uint Size;
public List<DirectoryTableEntry> directoryTable = new List<DirectoryTableEntry>();
public List<EntryNameTableEntry> entryNameTable = new List<EntryNameTableEntry>();
public FileNameTable(FileReader reader)
{
long startPos = reader.BaseStream.Position;
reader.ReadSignature(4, "BTNF");
Size = reader.ReadUInt32();
directoryTable.Add(new DirectoryTableEntry(reader));
for (int i = 0; i < directoryTable[0].dirParentID - 1; i++)
{
directoryTable.Add(new DirectoryTableEntry(reader));
}
entryNameTable = new List<EntryNameTableEntry>();
int EndOfDirectory = 0;
while (EndOfDirectory < directoryTable[0].dirParentID)
{
byte entryNameLength = reader.ReadByte();
reader.BaseStream.Position--;
if (entryNameLength == 0)
{
entryNameTable.Add(new EntryNameTableEndOfDirectoryEntry(reader));
EndOfDirectory++;
}
else if (entryNameLength < 0x80) entryNameTable.Add(new EntryNameTableFileEntry(reader));
else entryNameTable.Add(new EntryNameTableDirectoryEntry(reader));
}
reader.BaseStream.Position = startPos + Size;
}
}
public class EntryNameTableEndOfDirectoryEntry : EntryNameTableEntry
{
public EntryNameTableEndOfDirectoryEntry() { }
public EntryNameTableEndOfDirectoryEntry(FileReader reader)
: base(reader) { }
public override void Write(FileWriter writer)
{
base.Write(writer);
}
}
public class EntryNameTableDirectoryEntry : EntryNameTableEntry
{
public string entryName;
public ushort directoryID;
public EntryNameTableDirectoryEntry(FileReader reader) : base(reader)
{
entryName = reader.ReadString(entryNameLength & 0x7F, Encoding.ASCII);
directoryID = reader.ReadUInt16();
}
public override void Write(FileWriter writer)
{
base.Write(writer);
writer.Write(entryName, Syroot.BinaryData.BinaryStringFormat.ZeroTerminated);
writer.Write(directoryID);
}
}
public class EntryNameTableFileEntry : EntryNameTableEntry
{
public string entryName;
public EntryNameTableFileEntry(FileReader reader) : base(reader)
{
entryName = reader.ReadString(entryNameLength, Encoding.ASCII);
}
public override void Write(FileWriter writer)
{
writer.Write(entryName, Syroot.BinaryData.BinaryStringFormat.ZeroTerminated);
}
}
public class EntryNameTableEntry
{
public byte entryNameLength;
protected EntryNameTableEntry() { }
public EntryNameTableEntry(FileReader reader)
{
entryNameLength = reader.ReadByte();
}
public virtual void Write(FileWriter writer)
{
writer.Write(entryNameLength);
}
}
public class DirectoryTableEntry
{
public uint dirEntryStart;
public ushort dirEntryFileID;
public ushort dirParentID;
public DirectoryTableEntry() { }
public DirectoryTableEntry(FileReader reader)
{
dirEntryStart = reader.ReadUInt32();
dirEntryFileID = reader.ReadUInt16();
dirParentID = reader.ReadUInt16();
}
public void Write(FileWriter writer)
{
writer.Write(dirEntryStart);
writer.Write(dirEntryFileID);
writer.Write(dirParentID);
}
}
}
}

View file

@ -0,0 +1,543 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Switch_Toolbox;
using System.Windows.Forms;
using SARCExt;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library.Forms;
namespace FirstPlugin
{
public class SARC : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "SARC", "SARC", "SARC", "SARC", "SARC" };
public string[] Extension { get; set; } = new string[] { "*.pack", "*.sarc", "*.bgenv", "*.sblarc", "*.sbactorpack" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "SARC");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public Dictionary<string, byte[]> OpenedFiles = new Dictionary<string, byte[]>();
public SarcData sarcData;
public string SarcHash;
public void Load(System.IO.Stream stream)
{
CanSave = true;
IFileInfo.UseEditMenu = true;
var SzsFiles = SARCExt.SARC.UnpackRamN(stream);
sarcData = new SarcData();
sarcData.HashOnly = false;
sarcData.Files = SzsFiles.Files;
sarcData.endianness = GetByteOrder(stream);
SarcHash = Utils.GenerateUniqueHashID();
FillTreeNodes(this, SzsFiles.Files, SarcHash);
Text = FileName;
ContextMenuStrip = new STContextMenuStrip();
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Save",null, Save, Keys.Control | Keys.S));
// ContextMenuStrip.Items.Add(new STToolStipMenuItem("Unpack to Folder", null, UnpackToFolder, Keys.Control | Keys.E));
// ContextMenuStrip.Items.Add(new STToolStipMenuItem("Pack From Folder", null, PackFromFolder, Keys.Control | Keys.R));
ContextMenuStrip.Items.Add(new STToolStripSeparator());
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Batch Texture Editor", null, PreviewTextures, Keys.Control | Keys.P));
ContextMenuStrip.Items.Add(new STToolStripSeparator());
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Sort Childern", null, SortChildern, Keys.Control | Keys.E));
sarcData.Files.Clear();
}
private void UnpackToFolder(object sender, EventArgs args)
{
}
private void PackFromFolder(object sender, EventArgs args)
{
}
private void SortChildern(object sender, EventArgs args)
{
TreeView.TreeViewNodeSorter = new TreeChildSorter();
TreeView.Sort();
}
public class FolderEntry : TreeNode
{
public FolderEntry(string text, int imageIndex, int selectedImageIndex)
{
Text = text;
ImageIndex = imageIndex;
SelectedImageIndex = selectedImageIndex;
ContextMenu = new ContextMenu();
ContextMenu.MenuItems.Add(new MenuItem("Sort Childern", SortChildern));
}
private void SortChildern(object sender, EventArgs args)
{
TreeView.TreeViewNodeSorter = new TreeChildSorter();
TreeView.Sort();
}
}
public Syroot.BinaryData.ByteOrder GetByteOrder(System.IO.Stream data)
{
using (FileReader reader = new FileReader(data))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
reader.Seek(6);
ushort bom = reader.ReadUInt16();
reader.Close();
reader.Dispose();
if (bom == 0xFFFE)
return Syroot.BinaryData.ByteOrder.LittleEndian;
else
return Syroot.BinaryData.ByteOrder.BigEndian;
}
}
public void Unload()
{
Nodes.Clear();
}
IEnumerable<TreeNode> Collect(TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
yield return node;
bool IsNodeFile = node is IFileFormat;
if (!IsNodeFile)
{
//We don't need to save the child of IFIleFormats
//If opened the file should save it's own children
foreach (var child in Collect(node.Nodes))
yield return child;
}
}
}
public byte[] Save()
{
Console.WriteLine("Saving sarc");
sarcData.Files.Clear();
foreach (TreeNode node in Collect(Nodes))
{
if (node is SarcEntry)
{
Console.WriteLine("Saving " + node);
SaveFileEntryData((SarcEntry)node);
}
else if (node is IFileFormat && node != this)
{
IFileFormat fileFormat = (IFileFormat)node;
if (fileFormat != null && ((IFileFormat)node).CanSave)
{
sarcData.Files.Add(SetSarcPath(node, this),
STLibraryCompression.CompressFile(fileFormat.Save(), fileFormat));
}
else
{
sarcData.Files.Add(SetSarcPath(node, this),
STLibraryCompression.CompressFile(OpenedFiles[node.FullPath], fileFormat));
}
}
}
Tuple<int, byte[]> sarc = SARCExt.SARC.PackN(sarcData);
IFileInfo.Alignment = sarc.Item1;
return sarc.Item2;
}
public static string SetSarcPath(TreeNode node, TreeNode sarcNode)
{
string nodePath = node.FullPath;
int startIndex = nodePath.IndexOf(sarcNode.Text);
if (startIndex > 0)
nodePath = nodePath.Substring(startIndex);
string slash = Path.DirectorySeparatorChar.ToString();
string slashAlt = Path.AltDirectorySeparatorChar.ToString();
string SetPath = nodePath.Replace(sarcNode.Text + slash, string.Empty).Replace(slash ?? "", slashAlt);
return !(SetPath == string.Empty) ? SetPath : node.Text;
}
private void SaveFileEntryData(SarcEntry sarc)
{
string dir = Path.GetDirectoryName(sarc.FullName);
if (dir == string.Empty)
sarc.FullName = sarc.Text;
else
sarc.FullName = Path.Combine(dir, sarc.Text);
sarcData.Files.Add(sarc.FullName, sarc.Data);
}
public static void ReplaceNode(TreeNode node, TreeNode replaceNode, TreeNode NewNode)
{
if (NewNode == null)
return;
int index = node.Nodes.IndexOf(replaceNode);
node.Nodes.RemoveAt(index);
node.Nodes.Insert(index, NewNode);
if (NewNode is TreeNodeFile)
((TreeNodeFile)NewNode).OnAfterAdded();
}
private void Save(object sender, EventArgs args)
{
List<IFileFormat> formats = new List<IFileFormat>();
formats.Add(this);
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = Utils.GetAllFilters(formats);
sfd.FileName = FileName;
if (sfd.ShowDialog() == DialogResult.OK)
{
STFileSaver.SaveFileFormat(this, sfd.FileName);
}
}
public static bool SuppressFormDialog = false;
private void PreviewTextures(object sender, EventArgs args)
{
SuppressFormDialog = true;
try
{
CallRecursive(TreeView);
CallRecursive(TreeView);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
PreviewEditor editor = new PreviewEditor();
editor.Show();
SuppressFormDialog = false;
}
private void CallRecursive(TreeView treeView)
{
// Print each node recursively.
TreeNodeCollection nodes = treeView.Nodes;
foreach (TreeNode n in nodes)
{
PrintRecursive(n);
}
}
private void PrintRecursive(TreeNode treeNode)
{
// Print the node.
if (treeNode is SarcEntry)
{
((SarcEntry)treeNode).OnDoubleMouseClick(treeNode.TreeView);
}
// Print each node recursively.
foreach (TreeNode tn in treeNode.Nodes)
{
PrintRecursive(tn);
}
}
public class SarcEntry : TreeNodeCustom
{
public SARC sarc; //Sarc file the entry is located in
public byte[] Data;
public string sarcHash;
public SarcEntry()
{
ImageKey = "fileBlank";
SelectedImageKey = "fileBlank";
ContextMenuStrip = new STContextMenuStrip();
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Export Raw Data", null, Export, Keys.Control | Keys.E));
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Export Raw Data to File Location", null, ExportToFileLoc, Keys.Control | Keys.F));
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Replace Raw Data", null, Replace, Keys.Control | Keys.R));
ContextMenuStrip.Items.Add(new STToolStripSeparator());
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Open With Text Editor", null, OpenTextEditor, Keys.Control | Keys.T));
ContextMenuStrip.Items.Add(new STToolStripSeparator());
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Remove", null, Remove, Keys.Control | Keys.Delete));
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Rename", null, Rename, Keys.Control | Keys.N));
}
public override void OnClick(TreeView treeView)
{
UpdateHexView();
}
private void UpdateHexView()
{
HexEditor editor = (HexEditor)LibraryGUI.Instance.GetActiveContent(typeof(HexEditor));
if (editor == null)
{
editor = new HexEditor();
LibraryGUI.Instance.LoadEditor(editor);
}
editor.Text = Text;
editor.Dock = DockStyle.Fill;
editor.LoadData(Data);
}
public override void OnDoubleMouseClick(TreeView treeView)
{
IFileFormat file = STFileLoader.OpenFileFormat(FullName, Data,false, true, this);
if (file != null && file is TreeNode)
{
sarc.OpenedFiles.Add(FullPath, Data);
ReplaceNode(this.Parent, this, (TreeNode)file);
}
else if (file != null && !SuppressFormDialog)
{
OpenFormDialog(file);
}
}
private void OpenFormDialog(IFileFormat fileFormat)
{
Type objectType = fileFormat.GetType();
foreach (var inter in objectType.GetInterfaces())
{
if (inter.IsGenericType && inter.GetGenericTypeDefinition() == typeof(IEditor<>))
{
System.Reflection.MethodInfo method = objectType.GetMethod("OpenForm");
var form = (STForm)method.Invoke(fileFormat, new object[0]);
form.Text = (((IFileFormat)fileFormat).FileName);
if (form.ShowDialog() == DialogResult.OK)
{
if (fileFormat.CanSave)
{
Data = fileFormat.Save();
UpdateHexView();
}
}
}
}
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
TreeNode node = TreeView.SelectedNode;
// Determine by checking the Text property.
}
public string FullName;
private void Replace(object sender, EventArgs args)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.FileName = Text;
ofd.DefaultExt = Path.GetExtension(Text);
ofd.Filter = "Raw Data (*.*)|*.*";
if (ofd.ShowDialog() == DialogResult.OK)
{
Data = File.ReadAllBytes(ofd.FileName);
}
}
private void ExportToFileLoc(object sender, EventArgs args)
{
Cursor.Current = Cursors.WaitCursor;
File.WriteAllBytes($"{Path.GetDirectoryName(sarc.FilePath)}/{Text}", Data);
Cursor.Current = Cursors.Default;
}
private void Export(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = Text;
sfd.DefaultExt = Path.GetExtension(Text);
sfd.Filter = "Raw Data (*.*)|*.*";
if (sfd.ShowDialog() == DialogResult.OK)
{
File.WriteAllBytes(sfd.FileName, Data);
}
}
private void OpenTextEditor(object sender, EventArgs args)
{
TextEditor editor = (TextEditor)LibraryGUI.Instance.GetActiveContent(typeof(TextEditor));
if (editor == null)
{
editor = new TextEditor();
LibraryGUI.Instance.LoadEditor(editor);
}
editor.Text = Text;
editor.Dock = DockStyle.Fill;
editor.FillEditor(Data);
}
private void Remove(object sender, EventArgs args)
{
DialogResult result = MessageBox.Show($"Are your sure you want to remove {Text}? This cannot be undone!", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
Parent.Nodes.Remove(this);
}
}
private void Rename(object sender, EventArgs args)
{
RenameDialog dialog = new RenameDialog();
dialog.SetString(Text);
if (dialog.ShowDialog() == DialogResult.OK)
{
Text = dialog.textBox1.Text;
}
}
}
void FillTreeNodes(TreeNode root, Dictionary<string, byte[]> files, string SarcHash)
{
var rootText = root.Text;
var rootTextLength = rootText.Length;
var nodeStrings = files;
foreach (var node in nodeStrings)
{
string nodeString = node.Key;
var roots = nodeString.Split(new char[] { '/' },
StringSplitOptions.RemoveEmptyEntries);
// The initial parent is the root node
var parentNode = root;
var sb = new StringBuilder(rootText, nodeString.Length + rootTextLength);
for (int rootIndex = 0; rootIndex < roots.Length; rootIndex++)
{
// Build the node name
var parentName = roots[rootIndex];
sb.Append("/");
sb.Append(parentName);
var nodeName = sb.ToString();
// Search for the node
var index = parentNode.Nodes.IndexOfKey(nodeName);
if (index == -1)
{
// Node was not found, add it
var folder = new FolderEntry(parentName, 0, 0);
if (rootIndex == roots.Length - 1)
{
var file = SetupFileEntry(node.Value, parentName, node.Key, SarcHash);
file.Name = nodeName;
parentNode.Nodes.Add(file);
parentNode = file;
}
else
{
folder.Name = nodeName;
parentNode.Nodes.Add(folder);
parentNode = folder;
}
}
else
{
// Node was found, set that as parent and continue
parentNode = parentNode.Nodes[index];
}
}
}
}
List<string> BuildFinalList(List<string> paths)
{
var finalList = new List<string>();
foreach (var path in paths)
{
bool found = false;
foreach (var item in finalList)
{
if (item.StartsWith(path, StringComparison.Ordinal))
{
found = true;
break;
}
}
if (!found)
{
finalList.Add(path);
}
}
return finalList;
}
public SarcEntry SetupFileEntry(byte[] data, string name, string fullName, string SarchHash)
{
SarcEntry sarcEntry = new SarcEntry();
sarcEntry.FullName = fullName;
sarcEntry.Name = name;
sarcEntry.Text = name;
sarcEntry.sarc = this;
sarcEntry.Data = data;
sarcEntry.sarcHash = SarcHash;
Console.WriteLine(name);
string ext = Path.GetExtension(name);
string SarcEx = SARCExt.SARC.GuessFileExtension(data);
if (SarcEx == ".bfres" || ext == ".sbfres")
{
sarcEntry.ImageKey = "bfres";
sarcEntry.SelectedImageKey = "bfres";
}
if (SarcEx == ".bntx")
{
sarcEntry.ImageKey = "bntx";
sarcEntry.SelectedImageKey = "bntx";
}
if (SarcEx == ".byaml")
{
sarcEntry.ImageKey = "byaml";
sarcEntry.SelectedImageKey = "byaml";
}
if (SarcEx == ".aamp")
{
sarcEntry.ImageKey = "aamp";
sarcEntry.SelectedImageKey = "aamp";
}
return sarcEntry;
}
}
}

View file

@ -0,0 +1,394 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.IO;
namespace FirstPlugin
{
public class SDF : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Snow Engine Data Table Of Contents" };
public string[] Extension { get; set; } = new string[] { "*.sdftoc" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "WEST");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
SDFTOC_Header Header;
SDFTOC_ID startId;
int[] block1;
SDFTOC_ID[] blockIds;
SDFTOC_Block2[] block2Array;
byte[] DecompressedBlock;
SDFTOC_ID endId;
List<string> FilePaths = new List<string>();
//Thanks to https://github.com/GoldFarmer/rouge_sdf/blob/master/main.cpp for docs/structs
public void Load(System.IO.Stream stream)
{
using (var reader = new FileReader(stream))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
//Read header
Header = new SDFTOC_Header();
Header.Read(reader);
//Read first id
startId = new SDFTOC_ID(reader);
//Check this flag
byte Flag1 = reader.ReadByte();
if (Flag1 != 0)
{
byte[] unk = reader.ReadBytes(0x140);
}
//Read first block
block1 = reader.ReadInt32s((int)Header.Block1Count);
//Read ID blocks
blockIds = new SDFTOC_ID[Header.Block1Count];
for (int i = 0; i < Header.Block1Count; i++)
{
blockIds[i] = new SDFTOC_ID(reader);
}
//Read block 2 (DDS headers)
block2Array = new SDFTOC_Block2[Header.Block2Count];
for (int i = 0; i < Header.Block2Count; i++)
{
block2Array[i] = new SDFTOC_Block2(reader, Header);
}
//Here is the compressed block. Check the magic first
uint magic = reader.ReadUInt32();
reader.Seek(-4, SeekOrigin.Current);
//Read and decompress the compressed block
//Contains file names and block info
DecompressNameBlock(magic, reader.ReadBytes((int)Header.CompressedSize), Header);
//Read last id
endId = new SDFTOC_ID(reader);
Text = FileName;
LoadTree();
}
}
private void LoadTree()
{
// Get a list of everything under the users' temp folder as an example
string[] fileList;
fileList = FilePaths.ToArray();
// Parse the file list into a TreeNode collection
// TreeNode node = GetNodes(new TreeNode(), fileList);
// Nodes.Add(node); // Add the new nodes
// Copy the new nodes to an array
// int nodeCount = node.Nodes.Count;
// TreeNode[] nodes = new TreeNode[nodeCount];
// node.Nodes.CopyTo(nodes, 0);
// Nodes.AddRange(nodes); // Add the new nodes
}
private TreeNode GetNodes(TreeNode parent, string[] fileList)
{
// build a TreeNode collection from the file list
foreach (string strPath in fileList)
{
// Every time we parse a new file path, we start at the top level again
TreeNode thisParent = parent;
// split the file path into pieces at every backslash
foreach (string pathPart in strPath.Split('\\'))
{
// check if we already have a node for this
TreeNode[] tn = thisParent.Nodes.Find(pathPart, false);
if (tn.Length == 0)
{
// no node found, so add one
thisParent = thisParent.Nodes.Add(pathPart, pathPart);
}
else
{
// we already have this node, so use it as the parent of the next part of the path
thisParent = tn[0];
}
}
}
return parent;
}
void FillTreeNodes(TreeNode root, List<string> files)
{
var rootText = root.Text;
var rootTextLength = rootText.Length;
var nodeStrings = files;
foreach (var node in nodeStrings)
{
string nodeString = node;
nodeString = nodeString.Replace(@"\", "/");
var roots = nodeString.Split(new char[] { '/' },
StringSplitOptions.RemoveEmptyEntries);
// The initial parent is the root node
var parentNode = root;
var sb = new StringBuilder(rootText, nodeString.Length + rootTextLength);
for (int rootIndex = 0; rootIndex < roots.Length; rootIndex++)
{
// Build the node name
var parentName = roots[rootIndex];
sb.Append("/");
sb.Append(parentName);
var nodeName = sb.ToString();
// Search for the node
var index = parentNode.Nodes.IndexOfKey(nodeName);
if (index == -1)
{
// Node was not found, add it
var temp = new TreeNode(parentName, 0, 0);
if (rootIndex == roots.Length - 1)
temp = new TreeNode(parentName); //File entry
temp.Name = nodeName;
parentNode.Nodes.Add(temp);
parentNode = temp;
}
else
{
// Node was found, set that as parent and continue
parentNode = parentNode.Nodes[index];
}
}
}
}
public void DecompressNameBlock(uint magic, byte[] CompressedBlock, SDFTOC_Header header)
{
byte[] decomp = null;
if (magic == 0xDFF25B82 || magic == 0xFD2FB528)
decomp = STLibraryCompression.ZSTD.Decompress(CompressedBlock);
else if (header.Version > 22)
decomp = STLibraryCompression.Type_LZ4.Decompress(CompressedBlock);
else
decomp = STLibraryCompression.ZLIB.Decompress(CompressedBlock, Header.DecompressedSize);
//Now it's decompressed lets parse!
using (var reader = new FileReader(decomp))
{
ParseNames(reader);
}
}
private ulong readVariadicInteger(int Count, FileReader reader)
{
ulong result = 0;
for (int i = 0; i < Count; i++)
{
result |= (ulong)(reader.ReadByte()) << (i * 8);
}
return result;
}
public void ParseNames(FileReader reader, string Name = "")
{
if (!Name.Contains("dummy"))
FilePaths.Add(Name);
char ch = reader.ReadChar();
if (ch == 0)
throw new Exception("Unexcepted byte in file tree");
if (ch >= 1 && ch <= 0x1f) //string part
{
while (ch-- != 0)
{
Name += reader.ReadChar();
}
ParseNames(reader, Name);
}
else if (ch >= 'A' && ch <= 'Z') //file entry
{
int var = Convert.ToInt32(ch - 'A');
ch = Convert.ToChar(var);
int count1 = ch >> 7;
int flag1 = (ch >> 3) & 1;
if (count1 != 0)
{
uint strangeId = reader.ReadUInt32();
byte chr2 = reader.ReadByte();
int byteCount = chr2 & 3;
int byteValue = chr2 >> 2;
ulong DdsType = readVariadicInteger(byteCount, reader);
for (int chunkIndex = 0; chunkIndex < count1; chunkIndex++)
{
byte ch3 = reader.ReadByte();
int compressedSizeByteCount = (ch3 & 3) + 1;
int packageOffsetByteCount = (ch3 >> 2) & 7;
int hasCompression = (ch3 >> 5) & 1;
ulong decompressedSize = readVariadicInteger(compressedSizeByteCount, reader);
ulong compressedSize = 0;
ulong packageOffset = 0;
if (hasCompression != 0)
{
compressedSize = readVariadicInteger(compressedSizeByteCount, reader);
}
if (packageOffsetByteCount != 0)
{
packageOffset = readVariadicInteger(packageOffsetByteCount, reader);
}
ulong packageId = readVariadicInteger(2, reader);
List<ulong> compSizeArray = new List<ulong>();
if (hasCompression != 0)
{
ulong pageCount = (decompressedSize + 0xffff) >> 16;
if (pageCount > 1)
{
for (ulong page = 0; page < pageCount; page++)
{
ulong compSize = readVariadicInteger(2, reader);
compSizeArray.Add(compSize);
}
}
}
ulong fileId = readVariadicInteger(4, reader);
if (compSizeArray.Count == 0 && hasCompression != 0)
compSizeArray.Add(compressedSize);
DumpFile(Name, packageId, packageOffset, decompressedSize, compSizeArray, DdsType, chunkIndex != 0, byteCount != 0 && chunkIndex == 0);
}
}
if (flag1 != 0)
{
byte ch3 = reader.ReadByte();
while (ch3-- != 0)
{
byte ch3_1 = reader.ReadByte();
byte ch3_2 = reader.ReadByte();
}
}
}
else
{
uint offset = reader.ReadUInt32();
ParseNames(reader, Name);
reader.Seek(offset, SeekOrigin.Begin);
ParseNames(reader, Name);
}
}
public void DumpFile(string Name, ulong packageId, ulong packageOffset, ulong decompresedSize,
List<ulong> compressedSize, ulong ddsType, bool Append, bool UseDDS)
{
string layer;
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
public class SDFTOC_Header
{
public uint Version { get; set; }
public uint DecompressedSize { get; set; }
public uint CompressedSize { get; set; }
public uint Zero { get; set; }
public uint Block1Count { get; set; }
public uint Block2Count { get; set; }
public void Read(FileReader reader)
{
reader.CheckSignature(4, "WEST");
reader.Seek(4, System.IO.SeekOrigin.Begin);
Version = reader.ReadUInt32();
DecompressedSize = reader.ReadUInt32();
CompressedSize = reader.ReadUInt32();
Zero = reader.ReadUInt32();
Block1Count = reader.ReadUInt32();
Block2Count = reader.ReadUInt32();
}
}
public class SDFTOC_ID
{
public ulong ubisoft { get; set; }
public byte[] Data { get; set; }
public ulong massive { get; set; }
public SDFTOC_ID(FileReader reader)
{
ubisoft = reader.ReadUInt64();
Data = reader.ReadBytes(0x20);
massive = reader.ReadUInt64();
}
}
public class SDFTOC_Block2 //Seems to be for DDS headers
{
public uint UsedBytes { get; set; }
public byte[] Data { get; set; }
public SDFTOC_Block2(FileReader reader, SDFTOC_Header header)
{
if (header.Version == 22)
{
UsedBytes = reader.ReadUInt32();
Data = reader.ReadBytes(0xC8);
}
else
{
UsedBytes = reader.ReadUInt32();
Data = reader.ReadBytes(0x94);
}
}
}
}
}

View file

@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library.Forms;
namespace FirstPlugin
{
public class TMPKFileInfo : ArchiveFileInfo
{
}
public class TMPK : TreeNodeFile, IArchiveFile
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "TMPK" };
public string[] Extension { get; set; } = new string[] { "*.pack" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "TMPK");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public IEnumerable<ArchiveFileInfo> Files { get; }
public bool CanAddFiles { get; set; } = true;
public bool CanRenameFiles { get; set; } = true;
public bool CanDelete { get; set; } = true;
public bool CanReplaceFiles { get; set; } = true;
public bool CanDeleteFiles { get; set; } = true;
public void Load(System.IO.Stream stream)
{
Text = FileName;
using (var reader = new FileReader(stream))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
reader.ReadSignature(4, "TMPK");
uint FileCount = reader.ReadUInt32();
uint Alignment = reader.ReadUInt32();
uint padding = reader.ReadUInt32();
for (int i = 0; i < FileCount; i++)
{
var info = new FileInfo(reader);
TMPKFileInfo archive = new TMPKFileInfo();
archive.FileData = new System.IO.MemoryStream(info.Data);
archive.Name = info.Text;
Nodes.Add(info);
}
}
}
public class FileInfo : TreeNodeCustom
{
public byte[] Data;
public FileInfo()
{
ContextMenu = new ContextMenu();
MenuItem export = new MenuItem("Export Raw Data");
ContextMenu.MenuItems.Add(export);
export.Click += Export;
}
private void Export(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = Text;
sfd.DefaultExt = Path.GetExtension(Text);
sfd.Filter = "Raw Data (*.*)|*.*";
if (sfd.ShowDialog() == DialogResult.OK)
{
File.WriteAllBytes(sfd.FileName, Data);
}
}
public override void OnClick(TreeView treeview)
{
HexEditor editor = (HexEditor)LibraryGUI.Instance.GetActiveContent(typeof(HexEditor));
if (editor == null)
{
editor = new HexEditor();
LibraryGUI.Instance.LoadEditor(editor);
}
editor.Text = Text;
editor.Dock = DockStyle.Fill;
editor.LoadData(Data);
}
public FileInfo(FileReader reader)
{
long pos = reader.Position;
uint NameOffset = reader.ReadUInt32();
uint FileOffset = reader.ReadUInt32();
uint FileSize = reader.ReadUInt32();
uint padding = reader.ReadUInt32();
reader.Seek(NameOffset, System.IO.SeekOrigin.Begin);
Text = reader.ReadString(Syroot.BinaryData.BinaryStringFormat.ZeroTerminated);
reader.Seek(FileOffset, System.IO.SeekOrigin.Begin);
Data = reader.ReadBytes((int)FileSize);
reader.Seek(pos + 16, System.IO.SeekOrigin.Begin);
ContextMenu = new ContextMenu();
MenuItem export = new MenuItem("Export Raw Data");
ContextMenu.MenuItems.Add(export);
export.Click += Export;
}
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
public bool AddFile(ArchiveFileInfo archiveFileInfo)
{
return false;
}
public bool DeleteFile(ArchiveFileInfo archiveFileInfo)
{
return false;
}
}
}

View file

@ -0,0 +1,211 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.IO;
using BarsLib;
using VGAudio.Formats;
using VGAudio;
using VGAudio.Containers.NintendoWare;
using VGAudio.Containers.Wave;
using NAudio.Wave;
namespace FirstPlugin
{
public class BARS : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Sound Archive" };
public string[] Extension { get; set; } = new string[] { "*.bars" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(Stream stream)
{
using (var reader = new FileReader(stream, true))
{
return reader.CheckSignature(4, "BARS");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public class AudioEntry : TreeNodeCustom
{
public AudioType Type;
public byte[] Data;
public AudioEntry()
{
ContextMenu = new ContextMenu();
MenuItem export = new MenuItem("Export");
ContextMenu.MenuItems.Add(export);
export.Click += Export;
MenuItem replace = new MenuItem("Replace");
ContextMenu.MenuItems.Add(replace);
replace.Click += Replace;
}
public void SetupMusic()
{
if (Type == AudioType.Bfwav)
{
ImageKey = "bfwav";
SelectedImageKey = "bfwav";
}
else if (Type == AudioType.Bfstp)
{
ImageKey = "bfstp";
SelectedImageKey = "bfstp";
}
else
{
ImageKey = "fileBlank";
SelectedImageKey = "fileBlank";
}
}
public AudioData GetAudioData()
{
BCFstmReader reader = new BCFstmReader();
return reader.Read(Data);
}
public byte[] BfwavToWav()
{
MemoryStream mem = new MemoryStream();
WaveWriter writer = new WaveWriter();
AudioData audioData = GetAudioData();
writer.WriteToStream(audioData, mem);
return mem.ToArray();
}
private void Export(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = Text;
sfd.DefaultExt = Path.GetExtension(Text);
sfd.Filter = "All files(*.*)|*.*";
if (sfd.ShowDialog() == DialogResult.OK)
{
File.WriteAllBytes(sfd.FileName, Data);
}
}
private void Replace(object sender, EventArgs args)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.FileName = Text;
ofd.DefaultExt = Path.GetExtension(Text);
ofd.Filter = "All files(*.*)|*.*";
if (ofd.ShowDialog() == DialogResult.OK)
{
Data = File.ReadAllBytes(ofd.FileName);
UpdateEditor();
}
}
public void UpdateEditor()
{
}
public override void OnClick(TreeView treeview)
{
if (Type == AudioType.Bfwav)
{
// UpdateEditor();
}
}
}
public BarsLib.BARS bars;
public void Load(Stream stream)
{
CanSave = true;
Text = FileName;
bars = new BarsLib.BARS(stream);
Nodes.Add("AMTA");
Nodes.Add("Audio");
for (int i = 0; i < bars.AmtaList.Count; i++)
{
string audioName = bars.AmtaList[i].Name;
Nodes[0].Nodes.Add(audioName + ".amta");
BARSAudioFile audio = bars.audioList[i];
AudioEntry node = new AudioEntry();
node.Type = audio.AudioType;
node.Data = audio.data;
node.SetupMusic();
if (audio.AudioType == AudioType.Bfwav)
node.Text = audioName + ".bfwav";
else if (audio.AudioType == AudioType.Bfstp)
node.Text = audioName + ".bfstp";
else
node.Text = audioName + ".UNKOWN";
Nodes[1].Nodes.Add(node);
}
ContextMenu = new ContextMenu();
MenuItem save = new MenuItem("Save");
ContextMenu.MenuItems.Add(save);
save.Click += Save;
}
public void Unload()
{
}
private void Save(object sender, EventArgs args)
{
List<IFileFormat> formats = new List<IFileFormat>();
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = Utils.GetAllFilters(formats);
sfd.FileName = FileName;
if (sfd.ShowDialog() == DialogResult.OK)
{
STFileSaver.SaveFileFormat(this, sfd.FileName);
}
}
public byte[] Save()
{
MemoryStream mem = new MemoryStream();
foreach (TreeNode node in Nodes[1].Nodes)
{
for (int i = 0; i < bars.AmtaList.Count; i++)
{
string audioName = bars.AmtaList[i].Name;
if (Path.GetFileNameWithoutExtension(node.Text) == audioName)
{
Console.WriteLine(audioName);
bars.audioList[i].data = ((AudioEntry)node).Data;
}
}
}
bars.Save(mem);
return mem.ToArray();
}
}
}

View file

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox.Library;
namespace FirstPlugin
{
public class BFGRP : IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Audio Group" };
public string[] Extension { get; set; } = new string[] { "*.bfgrp" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "FGRP");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public void Load(System.IO.Stream stream)
{
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
}
}

View file

@ -0,0 +1,246 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.IO;
namespace FirstPlugin
{
public class BFSAR : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Cafe Sound Archive" };
public string[] Extension { get; set; } = new string[] { "*.bfsar" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "FSAR");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public void Load(System.IO.Stream stream)
{
FSAR bfsar = new FSAR();
bfsar.Read(new FileReader(stream));
Text = FileName;
Nodes.Add("Audio List");
Nodes.Add("Audio Set List");
Nodes.Add("Bank List");
Nodes.Add("Group List");
Nodes.Add("Players List");
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
private static uint FileSizeOffset;
public class FSAR
{
public uint Size;
private ushort BOM;
public ushort HeaderSize;
public uint Version;
public ushort SectionCount;
public STRG STRG;
public INFO INFO;
public FILE FILE;
public void Read(FileReader reader)
{
string Signature = reader.ReadString(4, Encoding.ASCII);
if (Signature != "FSAR")
throw new Exception($"Invalid signature {Signature}! Expected FSAR.");
BOM = reader.ReadUInt16();
HeaderSize = reader.ReadUInt16();
Version = reader.ReadUInt32();
uint FileSize = reader.ReadUInt32();
SectionCount = reader.ReadUInt16();
ushort padding = reader.ReadUInt16();
for (int i = 0; i < SectionCount; i++)
{
ushort Identifier = reader.ReadUInt16();
ushort padding2 = reader.ReadUInt16();
uint Offset = reader.ReadUInt32();
uint Size = reader.ReadUInt32();
if (Identifier == 8192)
{
reader.Seek(Offset, SeekOrigin.Begin);
STRG = new STRG();
STRG.Read(reader);
}
if (Identifier == 8193)
{
reader.Seek(Offset, SeekOrigin.Begin);
INFO = new INFO();
INFO.Read(reader);
}
if (Identifier == 8194)
{
reader.Seek(Offset, SeekOrigin.Begin);
FILE = new FILE();
FILE.Read(reader, INFO);
}
}
reader.Close();
reader.Dispose();
}
public void Write(FileWriter writer)
{
writer.WriteSignature("FSAR");
writer.Write(BOM);
writer.Write(HeaderSize);
writer.Write(Version);
FileSizeOffset = (uint)writer.Position;
writer.Write(SectionCount);
writer.Write((ushort)0);
for (int i = 0; i < SectionCount; i++)
{
}
}
}
public class INFO
{
public uint SectionSize;
public AudioList audioList;
public void Read(FileReader reader)
{
string Signature = reader.ReadString(4, Encoding.ASCII);
if (Signature != "INFO")
throw new Exception($"Invalid signature {Signature}! Expected INFO.");
SectionSize = reader.ReadUInt32();
long Pos = reader.Position;
uint AudioListOffset = reader.ReadUInt32();
if (AudioListOffset != 0)
{
using (reader.TemporarySeek(AudioListOffset + Pos, SeekOrigin.Begin))
{
audioList = new AudioList();
audioList.Read(reader);
}
}
}
}
public class AudioList
{
public void Read(FileReader reader)
{
}
}
public class FILE
{
public uint SectionSize;
public void Read(FileReader reader, INFO INFO)
{
string Signature = reader.ReadString(4, Encoding.ASCII);
if (Signature != "FILE")
throw new Exception($"Invalid signature {Signature}! Expected FILE.");
SectionSize = reader.ReadUInt32();
byte[] padding = reader.ReadBytes(0x18);
}
}
public class STRG
{
public uint Size;
private uint BOM;
public uint SectionSize;
public uint Version;
public ushort SectionCount;
public StringTable stringTable;
public LookupTable lookupTable;
public void Read(FileReader reader)
{
string Signature = reader.ReadString(4, Encoding.ASCII);
if (Signature != "STRG")
throw new Exception($"Invalid signature {Signature}! Expected STRG.");
SectionSize = reader.ReadUInt32();
long pos = reader.Position;
uint unk = reader.ReadUInt32();
uint Stringtableoffset = reader.ReadUInt32();
uint unk2 = reader.ReadUInt32();
uint LookupTableOffset = reader.ReadUInt32();
if (Stringtableoffset != 0)
{
reader.Seek(Stringtableoffset + pos, SeekOrigin.Begin);
stringTable = new StringTable();
stringTable.Read(reader);
}
if (LookupTableOffset != 0)
{
reader.Seek(LookupTableOffset + pos, SeekOrigin.Begin);
lookupTable = new LookupTable();
lookupTable.Read(reader);
}
}
public class StringTable
{
public List<string> Names = new List<string>();
public void Read(FileReader reader)
{
long pos = reader.Position;
uint Count = reader.ReadUInt32();
for (int i = 0; i < Count; i++)
{
uint unk = reader.ReadUInt32();
uint Offset = reader.ReadUInt32();
uint Size = reader.ReadUInt32();
using (reader.TemporarySeek(Offset + pos, SeekOrigin.Begin))
{
Names.Add(reader.ReadString(Syroot.BinaryData.BinaryStringFormat.ZeroTerminated));
}
}
foreach (string name in Names)
Console.WriteLine(name);
}
}
public class LookupTable
{
public void Read(FileReader reader)
{
}
}
}
}
}

View file

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.IO;
namespace FirstPlugin
{
public class BARSLIST : IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Audio Archive List" };
public string[] Extension { get; set; } = new string[] { "*.barslist" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "ARSL");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public class BinaryData
{
public ushort Version;
public void Read(FileReader reader)
{
string Signature = reader.ReadSignature(4, "ARSL");
ushort bom = reader.ReadUInt16();
reader.CheckByteOrderMark(bom);
Version = reader.ReadUInt16();
uint padding = reader.ReadUInt32();
uint entryCount = reader.ReadUInt32();
}
}
public void Load(System.IO.Stream stream)
{
using (var reader = new FileReader(stream))
{
BinaryData data = new BinaryData();
}
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
}
}

View file

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using VGAudio.Formats;
using VGAudio.Containers.NintendoWare;
namespace FirstPlugin
{
public class BCSTM : VGAdudioFile, IEditor<AudioPlayer>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Cafe Stream" };
public string[] Extension { get; set; } = new string[] { "*.bcstm" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "CSTM");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public AudioPlayer OpenForm()
{
AudioPlayer form = new AudioPlayer();
form.Text = FileName;
form.Dock = DockStyle.Fill;
form.LoadFile(audioData, this);
return form;
}
public void Load(System.IO.Stream stream)
{
CanSave = true;
LoadAudio(stream, this);
}
public void Unload()
{
}
public byte[] Save()
{
return SaveAudio();
}
}
}

View file

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using VGAudio.Formats;
using VGAudio.Containers.NintendoWare;
namespace FirstPlugin
{
public class BCWAV : VGAdudioFile, IEditor<AudioPlayer>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Ctr Wave" };
public string[] Extension { get; set; } = new string[] { "*.bcwav" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "CWAV");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public AudioPlayer OpenForm()
{
AudioPlayer form = new AudioPlayer();
form.Text = FileName;
form.Dock = DockStyle.Fill;
form.LoadFile(audioData, this);
return form;
}
public void Load(System.IO.Stream stream)
{
CanSave = true;
LoadAudio(stream, this);
}
public void Unload()
{
}
public byte[] Save()
{
return SaveAudio();
}
}
}

View file

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using VGAudio.Formats;
using VGAudio.Containers.NintendoWare;
namespace FirstPlugin
{
public class BFSTM : VGAdudioFile, IEditor<AudioPlayer>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Cafe Stream" };
public string[] Extension { get; set; } = new string[] { "*.bfstm" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "FSTM");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public AudioPlayer OpenForm()
{
AudioPlayer form = new AudioPlayer();
form.Text = FileName;
form.Dock = DockStyle.Fill;
try
{
form.LoadFile(audioData, this);
}
catch (Exception ex)
{
STErrorDialog.Show("Failed to open audio player!", "Audio Player" , ex.ToString());
}
return form;
}
public void Load(System.IO.Stream stream)
{
CanSave = true;
LoadAudio(stream, this);
}
public void Unload()
{
}
public byte[] Save()
{
return SaveAudio();
}
}
}

View file

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using VGAudio.Formats;
using VGAudio.Containers.NintendoWare;
namespace FirstPlugin
{
public class BFWAV : VGAdudioFile, IEditor<AudioPlayer>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Cafe Wave" };
public string[] Extension { get; set; } = new string[] { "*.bfwav" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "FWAV");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public AudioPlayer OpenForm()
{
AudioPlayer form = new AudioPlayer();
form.Text = FileName;
form.Dock = DockStyle.Fill;
form.LoadFile(audioData, this);
return form;
}
public void Load(System.IO.Stream stream)
{
LoadAudio(stream, this);
}
public void Unload()
{
}
public byte[] Save()
{
return SaveAudio();
}
}
}

View file

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using VGAudio.Formats;
using VGAudio.Containers.NintendoWare;
namespace FirstPlugin
{
public class BRSTM : VGAdudioFile, IEditor<AudioPlayer>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Revolution Stream" };
public string[] Extension { get; set; } = new string[] { "*.brstm" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "RSTM");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public AudioPlayer OpenForm()
{
AudioPlayer form = new AudioPlayer();
form.Text = FileName;
form.Dock = DockStyle.Fill;
form.LoadFile(audioData, this);
return form;
}
public void Load(System.IO.Stream stream)
{
CanSave = true;
LoadAudio(stream, this);
}
public void Unload()
{
}
public byte[] Save()
{
return SaveAudio();
}
}
}

View file

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using VGAudio.Formats;
using VGAudio.Containers.NintendoWare;
namespace FirstPlugin
{
public class BRWAV : VGAdudioFile, IEditor<AudioPlayer>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Revolution Wave" };
public string[] Extension { get; set; } = new string[] { "*.brwav" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "RWAV");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public AudioPlayer OpenForm()
{
AudioPlayer form = new AudioPlayer();
form.Text = FileName;
form.Dock = DockStyle.Fill;
form.LoadFile(audioData, this);
return form;
}
public void Load(System.IO.Stream stream)
{
LoadAudio(stream, this);
}
public void Unload()
{
}
public byte[] Save()
{
return SaveAudio();
}
}
}

View file

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using VGAudio.Formats;
using VGAudio.Containers.NintendoWare;
namespace FirstPlugin
{
public class HPS : VGAdudioFile, IEditor<AudioPlayer>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "hps" };
public string[] Extension { get; set; } = new string[] { "*.HPS" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(8, " HALPST\0");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public AudioPlayer OpenForm()
{
AudioPlayer form = new AudioPlayer();
form.Text = FileName;
form.Dock = DockStyle.Fill;
form.LoadFile(audioData, this);
return form;
}
public void Load(System.IO.Stream stream)
{
CanSave = true;
LoadAudio(stream, this);
}
public void Unload()
{
}
public byte[] Save()
{
return SaveAudio();
}
}
}

View file

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using VGAudio.Formats;
using VGAudio.Containers.NintendoWare;
namespace FirstPlugin
{
public class IDSP : VGAdudioFile, IEditor<AudioPlayer>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "IDSP" };
public string[] Extension { get; set; } = new string[] { "*.idsp" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "IDSP");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public AudioPlayer OpenForm()
{
AudioPlayer form = new AudioPlayer();
form.Text = FileName;
form.Dock = DockStyle.Fill;
form.LoadFile(audioData, this);
return form;
}
public void Load(System.IO.Stream stream)
{
CanSave = true;
LoadAudio(stream, this);
}
public void Unload()
{
}
public byte[] Save()
{
return SaveAudio();
}
}
}

View file

@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using VGAudio.Formats;
using VGAudio.Containers.NintendoWare;
using CSCore;
using CSCore.Codecs;
namespace FirstPlugin
{
public class MP3 : IEditor<AudioPlayer>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "MPEG-1 Audio Layer-3" };
public string[] Extension { get; set; } = new string[] { "*.mp3" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
bool IsValidSig = reader.CheckSignature(3, "ID3");
bool IsValidExt = Utils.HasExtension(FileName, ".mp3");
if (IsValidExt || IsValidSig)
return true;
else
return false;
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public AudioPlayer OpenForm()
{
AudioPlayer form = new AudioPlayer();
form.Text = FileName;
form.Dock = DockStyle.Fill;
form.LoadFile(waveSource, this, mp3Struct);
return form;
}
IWaveSource waveSource;
object mp3Struct;
public void Load(System.IO.Stream stream)
{
CanSave = true;
waveSource = CodecFactory.Instance.GetCodec(stream, ".mp3");
stream.Position = 0;
mp3Struct = CSCore.Tags.ID3.ID3v1.FromStream(stream);
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
}
}

View file

@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using VGAudio.Formats;
using VGAudio.Containers.NintendoWare;
using CSCore;
using CSCore.Codecs;
namespace FirstPlugin
{
public class OGG : IEditor<AudioPlayer>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Ogg-vorbis" };
public string[] Extension { get; set; } = new string[] { "*.ogg" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
bool IsValidSig = reader.CheckSignature(4, "OggS");
bool IsValidExt = Utils.HasExtension(FileName, ".ogg");
if (IsValidExt || IsValidSig)
return true;
else
return false;
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public AudioPlayer OpenForm()
{
AudioPlayer form = new AudioPlayer();
form.Text = FileName;
form.Dock = DockStyle.Fill;
form.LoadFile(waveSource, this);
return form;
}
IWaveSource waveSource;
public void Load(System.IO.Stream stream)
{
stream.Position = 0;
CanSave = true;
waveSource = CodecFactory.Instance.GetCodec(stream, ".ogg");
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
}
}

View file

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using VGAudio.Formats;
using VGAudio.Containers.NintendoWare;
namespace FirstPlugin
{
public class WAV : IEditor<AudioPlayer>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Waveform Audio" };
public string[] Extension { get; set; } = new string[] { "*.wav" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
bool IsValidSig = reader.CheckSignature(4, "WAVE"); //RIFF is also used in avi so just use WAVE
bool IsValidExt = reader.CheckSignature(4, ".wav");
if (IsValidExt || IsValidSig)
return true;
else
return false;
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public AudioPlayer OpenForm()
{
AudioPlayer form = new AudioPlayer();
form.Text = FileName;
form.Dock = DockStyle.Fill;
form.LoadFile(audioData, this);
// form.AddFileContextEvent("Save", Save);
// form.AddFileContextEvent("Replace", Replace);
// form.LoadProperties(prop);
return form;
}
AudioData audioData;
public void Load(System.IO.Stream stream)
{
CanSave = true;
audioData = new BCFstmReader().Read(stream);
}
public void Unload()
{
}
public byte[] Save()
{
var writer = new BCFstmWriter(NwTarget.Ctr);
writer.Configuration = new BxstmConfiguration()
{
Endianness = VGAudio.Utilities.Endianness.LittleEndian,
};
return writer.GetFile(audioData, writer.Configuration);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,437 @@
using System;
using System.Windows.Forms;
using Switch_Toolbox.Library.NodeWrappers;
using Switch_Toolbox.Library.Animations;
using Switch_Toolbox.Library.Forms;
using Switch_Toolbox.Library;
using ResU = Syroot.NintenTools.Bfres;
using ResNX = Syroot.NintenTools.NSW.Bfres;
using FirstPlugin;
namespace Bfres.Structs
{
public class BFRESAnimFolder : STGenericWrapper
{
public BFRESAnimFolder()
{
Text = "Animations";
}
public bool IsWiiU { get; set; }
public override void OnClick(TreeView treeview)
{
if (Parent is BFRES)
((BFRES)Parent).LoadEditors(this);
else if (Parent.Parent is BFRES)
{
((BFRES)Parent.Parent).LoadEditors(this);
}
else
{
((BFRES)Parent.Parent.Parent).LoadEditors(this);
}
}
public ResNX.ResFile GetResFile()
{
return ((BFRES)Parent).resFile;
}
public ResU.ResFile GetResFileU()
{
return ((BFRES)Parent).resFileU;
}
public void AddNode(BFRESGroupNode node)
{
Nodes.Add(node);
}
public void LoadMenus(bool isWiiUBfres)
{
IsWiiU = isWiiUBfres;
ContextMenuStrip.Items.Clear();
ContextMenuStrip.Items.Add(new ToolStripMenuItem("New", null,
new ToolStripMenuItem("Skeletal Animation", null, NewSkeletalAnimAction),
new ToolStripMenuItem("Shader Param Animation", null, NewShaderParamAnimAction),
new ToolStripMenuItem("Color Animation", null, NewColorAnimAction),
new ToolStripMenuItem("Texture SRT Animations", null, NewTexSrtAnimAction),
new ToolStripMenuItem("Texture Pattern Animation", null, NewTexPatAnimAction),
new ToolStripMenuItem("Bone Visibility Animation", null, NewBoneVisAnimAction),
new ToolStripMenuItem("Material Visibility Animation", null, NewMatVisAnimAction),
new ToolStripMenuItem("Shape Aniation", null, NewShapeAnimAction),
new ToolStripMenuItem("Scene Aniation", null, NewSceneAnimAction)
));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Import", null,
new ToolStripMenuItem("Skeletal Animation", null, ImportSkeletalAnimAction),
new ToolStripMenuItem("Shader Param Animation", null, ImportShaderParamAnimAction),
new ToolStripMenuItem("Color Animation", null, ImportColorAnimAction),
new ToolStripMenuItem("Texture SRT Animations", null, ImportTexSrtAnimAction),
new ToolStripMenuItem("Texture Pattern Animation", null, ImportTexPatAnimAction),
new ToolStripMenuItem("Bone Visibility Animation", null, ImportBoneVisAnimAction),
new ToolStripMenuItem("Material Visibility Animation", null, ImportMatVisAnimAction),
new ToolStripMenuItem("Shape Aniation", null, ImportShapeAnimAction),
new ToolStripMenuItem("Scene Aniation", null, ImportSceneAnimAction)
));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Clear", null, ClearAction, Keys.Control | Keys.C));
}
protected void NewSkeletalAnimAction(object sender, EventArgs e) { NewSkeletalAnim(); }
protected void NewShaderParamAnimAction(object sender, EventArgs e) { NewShaderParamAnim(); }
protected void NewColorAnimAction(object sender, EventArgs e) { NewColorAnim(); }
protected void NewTexSrtAnimAction(object sender, EventArgs e) { NewTexSrtAnim(); }
protected void NewTexPatAnimAction(object sender, EventArgs e) { NewTexPatAnim(); }
protected void NewBoneVisAnimAction(object sender, EventArgs e) { NewBoneVisAnim(); }
protected void NewMatVisAnimAction(object sender, EventArgs e) { NewMatVisAnim(); }
protected void NewShapeAnimAction(object sender, EventArgs e) { NewShapeAnim(); }
protected void NewSceneAnimAction(object sender, EventArgs e) { NewSceneAnim(); }
protected void ImportSkeletalAnimAction(object sender, EventArgs e) { ImportSkeletalAnim(); }
protected void ImportShaderParamAnimAction(object sender, EventArgs e) { ImportShaderParamAnim(); }
protected void ImportColorAnimAction(object sender, EventArgs e) { ImportColorAnim(); }
protected void ImportTexSrtAnimAction(object sender, EventArgs e) { ImportTexSrtAnim(); }
protected void ImportTexPatAnimAction(object sender, EventArgs e) { ImportTexPatAnim(); }
protected void ImportBoneVisAnimAction(object sender, EventArgs e) { ImportBoneVisAnim(); }
protected void ImportMatVisAnimAction(object sender, EventArgs e) { ImportMatVisAnim(); }
protected void ImportShapeAnimAction(object sender, EventArgs e) { ImportShapeAnim(); }
protected void ImportSceneAnimAction(object sender, EventArgs e) { ImportSceneAnim(); }
public void ImportSkeletalAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = GetOrCreateFolder<FSKA>();
group.Import(ofd.FileNames, GetResFile(), GetResFileU());
AddFolder(group);
}
public void ImportShaderParamAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = null;
if (IsWiiU)
group = GetOrCreateFolder<FSHU>(MaterialAnimation.AnimationType.ShaderParam);
else
group = GetOrCreateFolder<FMAA>(MaterialAnimation.AnimationType.ShaderParam);
group.Import(ofd.FileNames, GetResFile(), GetResFileU());
AddFolder(group);
}
public void ImportColorAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = null;
if (IsWiiU)
group = GetOrCreateFolder<FSHU>(MaterialAnimation.AnimationType.Color);
else
group = GetOrCreateFolder<FMAA>(MaterialAnimation.AnimationType.Color);
group.Import(ofd.FileNames, GetResFile(), GetResFileU());
AddFolder(group);
}
public void ImportTexSrtAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = null;
if (IsWiiU)
group = GetOrCreateFolder<FSHU>(MaterialAnimation.AnimationType.ShaderParam);
else
group = GetOrCreateFolder<FMAA>(MaterialAnimation.AnimationType.ShaderParam);
group.Import(ofd.FileNames, GetResFile(), GetResFileU());
AddFolder(group);
}
public void ImportTexPatAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = null;
if (IsWiiU)
group = GetOrCreateFolder<FTXP>();
else
group = GetOrCreateFolder<FMAA>(MaterialAnimation.AnimationType.TexturePattern);
group.Import(ofd.FileNames, GetResFile(), GetResFileU());
AddFolder(group);
}
public void ImportBoneVisAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = GetOrCreateFolder<FVIS>(VisibiltyAnimType.Bone);
group.Import(ofd.FileNames, GetResFile(), GetResFileU());
AddFolder(group);
}
public void ImportMatVisAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = null;
if (IsWiiU)
group = GetOrCreateFolder<FVIS>(VisibiltyAnimType.Material);
else
group = GetOrCreateFolder<FMAA>(MaterialAnimation.AnimationType.Visibilty);
group.Import(ofd.FileNames, GetResFile(), GetResFileU());
AddFolder(group);
}
public void ImportSceneAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = GetOrCreateFolder<FSCN>();
group.Import(ofd.FileNames, GetResFile(), GetResFileU());
AddFolder(group);
}
public void ImportShapeAnim()
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() != DialogResult.OK)
return;
BFRESGroupNode group = GetOrCreateFolder<FSHA>();
group.Import(ofd.FileNames, GetResFile(), GetResFileU());
AddFolder(group);
}
public void NewSkeletalAnim()
{
BFRESGroupNode group = GetOrCreateFolder<FSKA>();
FSKA anim = null;
if (IsWiiU)
anim = new FSKA(new ResU.SkeletalAnim());
else
anim = new FSKA(new ResNX.SkeletalAnim());
group.AddNode(anim, "NewSkeletalAnim");
AddFolder(group);
}
public void NewShaderParamAnim()
{
var type = MaterialAnimation.AnimationType.ShaderParam;
BFRESGroupNode group = null;
if (IsWiiU)
{
group = GetOrCreateFolder<FSHU>(type);
FSHU fshu = new FSHU(new ResU.ShaderParamAnim(), type);
group.AddNode(fshu, "NewShaderParamAnim");
}
else
{
group = GetOrCreateFolder<FMAA>(type);
FMAA fmaa = new FMAA(new ResNX.MaterialAnim(), type);
group.AddNode(fmaa, "NewShaderParamAnim");
}
AddFolder(group);
}
public void NewColorAnim()
{
var type = MaterialAnimation.AnimationType.Color;
BFRESGroupNode group = null;
if (IsWiiU)
{
group = GetOrCreateFolder<FSHU>(type);
FSHU fshu = new FSHU(new ResU.ShaderParamAnim(), type);
group.AddNode(fshu, "NewColorAnim");
}
else
{
group = GetOrCreateFolder<FMAA>(type);
FMAA fmaa = new FMAA(new ResNX.MaterialAnim(), type);
group.AddNode(fmaa, "NewColorAnim");
}
AddFolder(group);
}
public void NewTexSrtAnim()
{
var type = MaterialAnimation.AnimationType.TextureSrt;
BFRESGroupNode group = null;
if (IsWiiU)
{
group = GetOrCreateFolder<FSHU>(type);
FSHU fshu = new FSHU(new ResU.ShaderParamAnim(), type);
group.AddNode(fshu, "NewTextureTransformAnim");
}
else
{
group = GetOrCreateFolder<FMAA>(type);
FMAA fmaa = new FMAA(new ResNX.MaterialAnim(), type);
group.AddNode(fmaa, "NewTextureTransformAnim");
}
AddFolder(group);
}
public void NewTexPatAnim()
{
var type = MaterialAnimation.AnimationType.TexturePattern;
BFRESGroupNode group = null;
if (IsWiiU)
{
group = GetOrCreateFolder<FTXP>();
FTXP anim = new FTXP(new ResU.TexPatternAnim());
group.AddNode(anim, "NewTexturePatternAnim");
}
else
{
group = GetOrCreateFolder<FMAA>(type);
FMAA fmaa = new FMAA(new ResNX.MaterialAnim(), type);
group.AddNode(fmaa, "NewTexturePatternAnim");
}
AddFolder(group);
}
public void NewBoneVisAnim()
{
BFRESGroupNode group = GetOrCreateFolder<FVIS>(VisibiltyAnimType.Bone);
FVIS anim = null;
if (IsWiiU)
{
anim = new FVIS(new ResU.VisibilityAnim() { Type = ResU.VisibilityAnimType.Bone });
}
else
{
anim = new FVIS(new ResNX.VisibilityAnim());
}
group.AddNode(anim, "NewBoneVisAnim");
AddFolder(group);
}
public void NewMatVisAnim()
{
BFRESGroupNode group = null;
if (IsWiiU)
{
group = GetOrCreateFolder<FVIS>(VisibiltyAnimType.Material);
FVIS anim = new FVIS(new ResU.VisibilityAnim() { Type = ResU.VisibilityAnimType.Material });
group.AddNode(anim, "NewMatVisAnim");
}
else
{
group = GetOrCreateFolder<FMAA>(MaterialAnimation.AnimationType.Visibilty);
FMAA fmaa = new FMAA(new ResNX.MaterialAnim(), MaterialAnimation.AnimationType.Visibilty);
group.AddNode(fmaa, "NewMatVisAnim");
}
AddFolder(group);
}
public void NewShapeAnim()
{
BFRESGroupNode group = GetOrCreateFolder<FSHA>();
FSHA anim = null;
if (IsWiiU)
anim = new FSHA(new ResU.ShapeAnim());
else
anim = new FSHA(new ResNX.ShapeAnim());
group.AddNode(anim, "NewShapeAnim");
AddFolder(group);
}
public void NewSceneAnim()
{
BFRESGroupNode group = GetOrCreateFolder<FSCN>();
FSCN fshu = null;
if (IsWiiU)
fshu = new FSCN(new ResU.SceneAnim());
else
fshu = new FSCN(new ResNX.SceneAnim());
group.AddNode(fshu, "NewSceneVisAnim");
AddFolder(group);
}
private void AddFolder(BFRESGroupNode group)
{
if (!Nodes.Contains(group))
Nodes.Add(group);
}
public BFRESGroupNode GetOrCreateFolder<T>(object CheckAnimEffect = null) where T : STGenericWrapper
{
BFRESGroupNode group = new BFRESGroupNode();
if (typeof(T) == typeof(FSKA)) { group.Type = BRESGroupType.SkeletalAnim; }
if (typeof(T) == typeof(FMAA)) { group.Type = BRESGroupType.MaterialAnim; }
if (typeof(T) == typeof(FSHU)) { group.Type = BRESGroupType.ShaderParamAnim; }
if (typeof(T) == typeof(FVIS)) { group.Type = BRESGroupType.BoneVisAnim; }
if (typeof(T) == typeof(FSHA)) { group.Type = BRESGroupType.ShapeAnim; }
if (typeof(T) == typeof(FSCN)) { group.Type = BRESGroupType.SceneAnim; }
if (typeof(T) == typeof(FTXP)) { group.Type = BRESGroupType.TexPatAnim; }
if (CheckAnimEffect != null)
{
if (CheckAnimEffect is MaterialAnimation.AnimationType)
{
var type = (MaterialAnimation.AnimationType)CheckAnimEffect;
if (type == MaterialAnimation.AnimationType.Color) { group.Type = BRESGroupType.ColorAnim; }
if (type == MaterialAnimation.AnimationType.TextureSrt) { group.Type = BRESGroupType.TexSrtAnim; }
if (type == MaterialAnimation.AnimationType.ShaderParam) { group.Type = BRESGroupType.ShaderParamAnim; }
if (type == MaterialAnimation.AnimationType.TexturePattern) { group.Type = BRESGroupType.TexPatAnim; }
if (type == MaterialAnimation.AnimationType.Visibilty) { group.Type = BRESGroupType.MatVisAnim; }
}
if (CheckAnimEffect is VisibiltyAnimType)
{
var type = (VisibiltyAnimType)CheckAnimEffect;
if (type == VisibiltyAnimType.Bone) { group.Type = BRESGroupType.BoneVisAnim; }
if (type == VisibiltyAnimType.Material) { group.Type = BRESGroupType.MatVisAnim; }
}
}
group.SetNameByType();
foreach (BFRESGroupNode node in Nodes)
{
if (node.Type == group.Type)
return node;
}
return group;
}
}
}

View file

@ -0,0 +1,670 @@
using Switch_Toolbox.Library.NodeWrappers;
using Switch_Toolbox.Library;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System;
using FirstPlugin;
using ResU = Syroot.NintenTools.Bfres;
using ResNX = Syroot.NintenTools.NSW.Bfres;
using Switch_Toolbox.Library.Animations;
using Switch_Toolbox.Library.Forms;
namespace Bfres.Structs
{
public enum BRESGroupType
{
Models,
Textures,
SkeletalAnim,
MaterialAnim,
ShaderParamAnim,
ColorAnim,
TexSrtAnim,
TexPatAnim,
BoneVisAnim,
MatVisAnim,
ShapeAnim,
SceneAnim,
Embedded,
}
public class BFRESGroupNode : STGenericWrapper
{
public bool IsWiiU
{
get
{
return ((BFRES)Parent).IsWiiU;
}
}
public override void OnClick(TreeView treeview)
{
if (Parent is BFRES)
((BFRES)Parent).LoadEditors(this);
else if (Parent.Parent is BFRES) {
((BFRES)Parent.Parent).LoadEditors(this);
}else {
((BFRES)Parent.Parent.Parent).LoadEditors(this);
}
}
public BFRESGroupNode() : base()
{
ImageKey = "folder";
LoadContextMenus();
}
public override void LoadContextMenus()
{
ContextMenuStrip = new STContextMenuStrip();
CanExport = false;
CanReplace = false;
CanRename = false;
CanDelete = false;
//Folder Operations
ContextMenuStrip.Items.Add(new STToolStipMenuItem("New", null, NewAction, Keys.Control | Keys.N));
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Import", null, ImportAction, Keys.Control | Keys.I));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Export All", null, ExportAllAction, Keys.Control | Keys.E));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Replace All", null, ReplaceAllAction, Keys.Control | Keys.R));
ContextMenuStrip.Items.Add(new STToolStripSeparator());
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Sort", null, SortAction, Keys.Control | Keys.S));
ContextMenuStrip.Items.Add(new STToolStipMenuItem("Clear", null, ClearAction, Keys.Control | Keys.C));
}
public override string ExportFilter { get { return GetSubfileExtensions(); } }
public override string ImportFilter { get { return GetSubfileExtensions(); } }
protected void NewAction(object sender, EventArgs e) { NewSubFile(); }
public BFRESGroupNode(string name) : base() { Text = name; }
public BFRESGroupNode(BRESGroupType type) : base() { Type = type; SetNameByType(); }
public BRESGroupType Type { get; set; }
public Dictionary<string, STGenericWrapper> ResourceNodes = new Dictionary<string, STGenericWrapper>(); //To get instance of classes
public ResNX.ResFile GetResFile() {
if (Parent is BFRES)
return ((BFRES)Parent).resFile;
else
return ((BFRES)Parent.Parent).resFile;
}
public ResU.ResFile GetResFileU() {
if (Parent is BFRES)
return ((BFRES)Parent).resFileU;
else
return ((BFRES)Parent.Parent).resFileU;
}
public void NewSubFile()
{
switch (Type)
{
case BRESGroupType.Models: NewModel(); break;
case BRESGroupType.SkeletalAnim: ((BFRESAnimFolder)Parent).NewSkeletalAnim(); break;
case BRESGroupType.ShaderParamAnim: ((BFRESAnimFolder)Parent).ImportShaderParamAnim(); break;
case BRESGroupType.ColorAnim: ((BFRESAnimFolder)Parent).NewColorAnim(); break;
case BRESGroupType.TexSrtAnim: ((BFRESAnimFolder)Parent).NewTexSrtAnim(); break;
case BRESGroupType.TexPatAnim: ((BFRESAnimFolder)Parent).NewTexPatAnim(); break;
case BRESGroupType.BoneVisAnim: ((BFRESAnimFolder)Parent).NewBoneVisAnim(); break;
case BRESGroupType.MatVisAnim: ((BFRESAnimFolder)Parent).NewMatVisAnim(); break;
case BRESGroupType.ShapeAnim: ((BFRESAnimFolder)Parent).NewShapeAnim(); break;
case BRESGroupType.SceneAnim: ((BFRESAnimFolder)Parent).NewSceneAnim(); break;
case BRESGroupType.Embedded: NewExternalFile(); break;
}
}
public void NewModel()
{
FMDL fmdl = new FMDL();
if (IsWiiU)
{
fmdl.ModelU = new ResU.Model();
//Create skeleton with empty bone
var skeleton = new ResU.Skeleton();
//Create skeleton with empty bone
skeleton.Bones.Add("Root", new ResU.Bone() { Name = "Root" });
fmdl.ModelU.Skeleton = skeleton;
var shape = new ResU.Shape() { Name = "NewShape" };
shape.CreateEmptyMesh();
var VertexBuffer = new ResU.VertexBuffer();
VertexBuffer.CreateEmptyVertexBuffer();
fmdl.ModelU.VertexBuffers.Add(VertexBuffer);
fmdl.ModelU.Shapes.Add("NewShape", shape);
fmdl.ModelU.Materials.Add("NewMaterial", new ResU.Material() { Name = "NewMaterial" });
BfresWiiU.ReadModel(fmdl, fmdl.ModelU);
}
else
{
fmdl.Model = new ResNX.Model();
//Create skeleton with empty bone
var skeleton = new ResNX.Skeleton();
//Create skeleton with empty bone
skeleton.Bones.Add(new ResNX.Bone() { Name = "Root" });
fmdl.Model.Skeleton = skeleton;
var shape = new ResNX.Shape() { Name = "NewShape" };
shape.CreateEmptyMesh();
fmdl.Model.Shapes.Add(shape);
fmdl.Model.Materials.Add(new ResNX.Material() { Name = "NewMaterial" });
var VertexBuffer = new ResNX.VertexBuffer();
VertexBuffer.CreateEmptyVertexBuffer();
fmdl.Model.VertexBuffers.Add(VertexBuffer);
BfresSwitch.ReadModel(fmdl, fmdl.Model);
}
AddNode(fmdl, "NewModel");
}
public void NewExternalFile()
{
ExternalFileData externalFileData = new ExternalFileData("NewExternalFile", new byte[0]);
AddNode(externalFileData, "NewExternalFile");
}
private string GetSubfileExtensions()
{
switch (Type)
{
case BRESGroupType.Models: return FileFilters.GetFilter(typeof(FMDL));
case BRESGroupType.Textures: return FileFilters.GetFilter(typeof(FTEX));
case BRESGroupType.SkeletalAnim: return FileFilters.GetFilter(typeof(FSKA));
case BRESGroupType.MaterialAnim: return FileFilters.GetFilter(typeof(FMAA));
case BRESGroupType.ShaderParamAnim: return FileFilters.GetFilter(typeof(FSHU));
case BRESGroupType.ColorAnim: return FileFilters.GetFilter(typeof(FSHU));
case BRESGroupType.TexSrtAnim: return FileFilters.GetFilter(typeof(FSHU));
case BRESGroupType.TexPatAnim: return FileFilters.GetFilter(typeof(FTXP));
case BRESGroupType.BoneVisAnim: return FileFilters.GetFilter(typeof(FVIS));
case BRESGroupType.MatVisAnim: return FileFilters.GetFilter(typeof(FVIS));
case BRESGroupType.ShapeAnim: return FileFilters.GetFilter(typeof(FSHA));
case BRESGroupType.SceneAnim: return FileFilters.GetFilter(typeof(FSCN));
case BRESGroupType.Embedded: return FileFilters.GetFilter(typeof(ExternalFileData));
default: return "All files(*.*)|*.*";
}
}
public override void Import(string[] FileNames) {
Import(FileNames, GetResFile(), GetResFileU());
}
public void Import(string[] FileNames, ResNX.ResFile resFileNX, ResU.ResFile resFileU)
{
if (Type == BRESGroupType.Textures)
{
ImportTexture(FileNames);
return;
}
foreach (string FileName in FileNames)
{
string ResourceName = Path.GetFileNameWithoutExtension(FileName);
string extension = Path.GetExtension(FileName);
switch (Type)
{
case BRESGroupType.Models:
FMDL fmdl = new FMDL();
fmdl.Text = ResourceName;
if (IsWiiU)
{
fmdl.ModelU = new ResU.Model();
fmdl.ModelU.Name = ResourceName;
var skeleton = new ResU.Skeleton();
//Create skeleton with empty bone
skeleton.Bones.Add("Root", new ResU.Bone() { Name = "Root" });
fmdl.ModelU.Skeleton = skeleton;
fmdl.ModelU.Shapes.Add("NeShape", new ResU.Shape() { Name = "NeShape" });
fmdl.ModelU.VertexBuffers.Add(new ResU.VertexBuffer() { });
}
else
{
fmdl.Model = new ResNX.Model();
fmdl.Model.Name = ResourceName;
//Create skeleton with empty bone
var skeleton = new ResNX.Skeleton();
skeleton.Bones.Add(new ResNX.Bone() { Name = "Root" });
fmdl.Model.Skeleton = skeleton;
fmdl.Model.Shapes.Add(new ResNX.Shape() { Name = "NeShape" });
fmdl.Model.VertexBuffers.Add(new ResNX.VertexBuffer() { });
BfresSwitch.ReadModel(fmdl, fmdl.Model);
}
fmdl.Replace(FileName, resFileNX, resFileU);
Nodes.Add(fmdl);
fmdl.UpdateVertexData();
break;
case BRESGroupType.SkeletalAnim:
FSKA fska = new FSKA();
fska.Text = ResourceName;
if (IsWiiU)
fska.SkeletalAnimU = new ResU.SkeletalAnim();
else
fska.SkeletalAnim = new ResNX.SkeletalAnim();
fska.Replace(FileName, resFileNX, resFileU);
Nodes.Add(fska);
break;
case BRESGroupType.ShaderParamAnim:
FSHU fshu = new FSHU(new ResU.ShaderParamAnim(), MaterialAnimation.AnimationType.ShaderParam);
fshu.Text = ResourceName;
fshu.Replace(FileName, resFileU);
Nodes.Add(fshu);
break;
case BRESGroupType.ColorAnim:
FSHU fclh = new FSHU(new ResU.ShaderParamAnim(), MaterialAnimation.AnimationType.Color);
fclh.Text = ResourceName;
fclh.Replace(FileName, resFileU);
Nodes.Add(fclh);
break;
case BRESGroupType.TexSrtAnim:
FSHU fsth = new FSHU(new ResU.ShaderParamAnim(), MaterialAnimation.AnimationType.TextureSrt);
fsth.Text = ResourceName;
fsth.Replace(FileName, resFileU);
Nodes.Add(fsth);
break;
case BRESGroupType.TexPatAnim:
FTXP ftxp = new FTXP(new ResU.TexPatternAnim());
ftxp.Text = ResourceName;
ftxp.Replace(FileName, resFileU);
Nodes.Add(ftxp);
break;
case BRESGroupType.BoneVisAnim:
FVIS fbnv = new FVIS();
fbnv.Text = ResourceName;
if (IsWiiU)
fbnv.VisibilityAnimU = new ResU.VisibilityAnim() { Type = ResU.VisibilityAnimType.Bone };
else
fbnv.VisibilityAnim = new ResNX.VisibilityAnim();
fbnv.Replace(FileName, resFileNX, resFileU);
Nodes.Add(fbnv);
break;
case BRESGroupType.MatVisAnim:
FVIS fmtv = new FVIS(new ResU.VisibilityAnim() { Type = ResU.VisibilityAnimType.Material });
fmtv.Text = ResourceName;
fmtv.Replace(FileName, resFileNX, resFileU);
Nodes.Add(fmtv);
break;
case BRESGroupType.ShapeAnim:
FSHA fsha = new FSHA();
fsha.Text = ResourceName;
if (IsWiiU)
fsha.ShapeAnimU = new ResU.ShapeAnim();
else
fsha.ShapeAnim = new ResNX.ShapeAnim();
fsha.Replace(FileName, resFileNX, resFileU);
Nodes.Add(fsha);
break;
case BRESGroupType.SceneAnim:
FSCN fscn = new FSCN();
fscn.Text = ResourceName;
if (IsWiiU)
fscn.SceneAnimU = new ResU.SceneAnim();
else
fscn.SceneAnim = new ResNX.SceneAnim();
fscn.Replace(FileName, resFileNX, resFileU);
Nodes.Add(fscn);
break;
case BRESGroupType.Embedded:
ExternalFileData ext = new ExternalFileData(ResourceName, File.ReadAllBytes(FileName));
ext.Replace(FileName);
Nodes.Add(ext);
break;
case BRESGroupType.MaterialAnim:
FMAA fmaa = new FMAA(new ResNX.MaterialAnim(), MaterialAnimation.AnimationType.ShaderParam);
fmaa.Replace(FileName);
Nodes.Add(fmaa);
break;
}
}
}
public void AddNode(STGenericWrapper node, string Name)
{
node.Text = SearchDuplicateName(Name);
AddNode(node);
}
public void AddNode(STGenericWrapper node)
{
if (node.Text == string.Empty)
throw new System.Exception("Text invalid. Must not be empty! ");
Nodes.Add(node);
ResourceNodes.Add(node.Text, node);
}
public void RemoveChild(STGenericWrapper node)
{
Nodes.Remove(node);
ResourceNodes.Remove(node.Text);
}
public override void Clear()
{
var result = MessageBox.Show("Are you sure you want to clear this section? This cannot be undone!",
"", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
foreach (var node in Nodes)
{
if (node is STGenericWrapper)
{
((STGenericWrapper)node).Unload();
RemoveChild(((STGenericWrapper)node));
}
}
Nodes.Clear();
}
}
public STGenericWrapper GetFirstChild()
{
if (Nodes.Count > 0 && Nodes[0] is STGenericWrapper)
return (STGenericWrapper)Nodes[0];
else
return new STGenericWrapper();
}
public void SetNameByType()
{
Text = SetName();
}
private string SetName()
{
switch (Type)
{
case BRESGroupType.Models: return "Models";
case BRESGroupType.Textures: return "Textures";
case BRESGroupType.SkeletalAnim: return "Skeletal Animations";
case BRESGroupType.ShaderParamAnim: return "Shader Param Animations";
case BRESGroupType.ColorAnim: return "Color Animations";
case BRESGroupType.TexSrtAnim: return "Texture SRT Animations";
case BRESGroupType.TexPatAnim: return "Texture Pattern Animations";
case BRESGroupType.BoneVisAnim: return "Bone Visibilty Animations";
case BRESGroupType.MatVisAnim: return "Material Visibilty Animations";
case BRESGroupType.ShapeAnim: return "Shape Animations";
case BRESGroupType.SceneAnim: return "Scene Animations";
case BRESGroupType.Embedded: return "Embedded Files";
case BRESGroupType.MaterialAnim: return "Material Animations";
default:
throw new System.Exception("Unknown type? " + Type);
}
}
public void GetFileType()
{
var child = GetFirstChild();
if (Text == "Models" || child is FMDL)
Type = BRESGroupType.Models;
if (Text == "Textures" || child is FTEX)
Type = BRESGroupType.Textures;
if (Text == "Skeleton Animations" || child is FSKA)
Type = BRESGroupType.SkeletalAnim;
if (Text == "Material Animations" || child is FMAA)
Type = BRESGroupType.MaterialAnim;
if (Text == "Shader Param Animations" || child is FSHU)
Type = BRESGroupType.ShaderParamAnim;
if (Text == "Color Animations" || child is FSHU)
Type = BRESGroupType.ColorAnim;
if (Text == "Texture Srt Animations" || child is FSHU)
Type = BRESGroupType.TexSrtAnim;
if (Text == "Texture Pattern Animations" || child is FTXP)
Type = BRESGroupType.TexPatAnim;
if (Text == "Bone Visibilty Animations" || child is FVIS)
Type = BRESGroupType.BoneVisAnim;
if (Text == "Material Visibilty Animations" || child is FVIS)
Type = BRESGroupType.MatVisAnim;
if (Text == "Embedded Files" || child is ExternalFileData)
Type = BRESGroupType.Embedded;
}
int IndexStr = 0;
public string SearchDuplicateName(string Name)
{
if (ResourceNodes.ContainsKey(Name))
return SearchDuplicateName($"{Name}{IndexStr++}");
else
return Name;
}
public void ImportTexture(string[] FileNames)
{
GTXTextureImporter importer = new GTXTextureImporter();
List<GTXImporterSettings> settings = new List<GTXImporterSettings>();
foreach (string name in FileNames)
{
string TextureName = Path.GetFileNameWithoutExtension(name);
string ext = Path.GetExtension(name);
ext = ext.ToLower();
if (ext == ".bftex")
{
FTEX ftex = new FTEX();
ftex.texture = new ResU.Texture();
ftex.texture.Import(name, GetResFileU());
ftex.IsEdited = true;
ftex.Read(ftex.texture);
AddNode(ftex);
return;
}
else if (ext == ".dds" || ext == ".dds2")
{
FTEX ftex = new FTEX();
ftex.texture = new ResU.Texture();
GTXImporterSettings setting = FTEX.SetImporterSettings(name);
if (setting.DataBlockOutput != null)
{
var surface = setting.CreateGx2Texture(setting.DataBlockOutput[0]);
var tex = ftex.FromGx2Surface(surface, setting);
ftex.UpdateTex(tex);
ftex.IsEdited = true;
ftex.Read(ftex.texture);
ftex.LoadOpenGLTexture();
AddNode(ftex);
}
}
else
{
settings.Add(FTEX.SetImporterSettings(name));
}
}
if (settings.Count == 0)
{
importer.Dispose();
return;
}
importer.LoadSettings(settings);
if (importer.ShowDialog() == DialogResult.OK)
{
ImportTexture(settings);
}
settings.Clear();
GC.Collect();
Cursor.Current = Cursors.Default;
}
public GTXImporterSettings LoadSettings(System.Drawing.Image image, string Name)
{
var importer = new GTXImporterSettings();
importer.LoadBitMap(image, Name);
return importer;
}
private void ImportTexture(List<GTXImporterSettings> settings)
{
Cursor.Current = Cursors.WaitCursor;
foreach (var setting in settings)
{
if (setting.GenerateMipmaps)
{
setting.DataBlockOutput.Clear();
setting.DataBlockOutput.Add(setting.GenerateMips());
}
if (setting.DataBlockOutput != null)
{
FTEX ftex = new FTEX();
ftex.texture = new ResU.Texture();
var surface = setting.CreateGx2Texture(setting.DataBlockOutput[0]);
var tex = ftex.FromGx2Surface(surface, setting);
ftex.UpdateTex(tex);
ftex.IsEdited = true;
ftex.Read(ftex.texture);
ftex.LoadOpenGLTexture();
AddNode(ftex);
}
else
{
MessageBox.Show("Something went wrong???");
}
}
}
public void ImportTexture(ImageKeyFrame[] Keys, string TextureName)
{
if (ResourceNodes.ContainsKey(TextureName) || Type != BRESGroupType.Textures)
return;
GTXTextureImporter importer = new GTXTextureImporter();
List<GTXImporterSettings> settings = new List<GTXImporterSettings>();
foreach (var key in Keys) {
settings.Add(FTEX.SetImporterSettings(key.Image, $"{TextureName}{key.Frame}"));
}
importer.LoadSettings(settings);
if (importer.ShowDialog() == DialogResult.OK) {
ImportTexture(settings);
}
settings.Clear();
GC.Collect();
Cursor.Current = Cursors.Default;
}
public void ImportPlaceholderTexture(string TextureName)
{
if (ResourceNodes.ContainsKey(TextureName) || Type != BRESGroupType.Textures)
return;
if (TextureName == "Basic_Alb")
ImportBasicTextures("Basic_Alb");
else if (TextureName == "Basic_Nrm")
ImportBasicTextures("Basic_Nrm");
else if (TextureName == "Basic_Spm")
ImportBasicTextures("Basic_Spm");
else if (TextureName == "Basic_Sphere")
ImportBasicTextures("Basic_Sphere");
else if (TextureName == "Basic_Mtl")
ImportBasicTextures("Basic_Mtl");
else if (TextureName == "Basic_Rgh")
ImportBasicTextures("Basic_Rgh");
else if (TextureName == "Basic_MRA")
ImportBasicTextures("Basic_MRA");
else if (TextureName == "Basic_Bake_st0")
ImportBasicTextures("Basic_Bake_st0");
else if (TextureName == "Basic_Bake_st1")
ImportBasicTextures("Basic_Bake_st1");
else if (TextureName == "Basic_Emm")
ImportBasicTextures("Basic_Emm");
else
{
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.InjectTexErrored, TextureName);
}
}
private void ImportPlaceholderTexture(byte[] data, string TextureName)
{
GTXImporterSettings setting = new GTXImporterSettings();
setting.LoadDDS(TextureName, data);
var surface = setting.CreateGx2Texture(setting.DataBlockOutput[0]);
FTEX ftex = new FTEX();
ftex.texture = new ResU.Texture();
ftex.texture = ftex.FromGx2Surface(surface, setting);
ftex.IsEdited = true;
ftex.Read(ftex.texture);
AddNode(ftex);
ftex.LoadOpenGLTexture();
}
public void ImportBasicTextures(string TextureName, bool BC5Nrm = true)
{
if (ResourceNodes.ContainsKey(TextureName) || Type != BRESGroupType.Textures)
return;
if (TextureName == "Basic_Alb")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.InjectTexErrored, TextureName);
if (TextureName == "Basic_Nrm" && BC5Nrm)
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Basic_NrmBC5, TextureName);
if (TextureName == "Basic_Nrm" && BC5Nrm == false)
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Basic_Nrm, TextureName);
if (TextureName == "Basic_Spm")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Black, TextureName);
if (TextureName == "Basic_Sphere")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Black, TextureName);
if (TextureName == "Basic_Mtl")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Black, TextureName);
if (TextureName == "Basic_Rgh")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.White, TextureName);
if (TextureName == "Basic_MRA")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Black, TextureName);
if (TextureName == "Basic_Bake_st0")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Basic_Bake_st0, TextureName);
if (TextureName == "Basic_Bake_st1")
ImportPlaceholderTexture(FirstPlugin.Properties.Resources.Basic_Bake_st1, TextureName);
}
}
}

View file

@ -0,0 +1,313 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Syroot.NintenTools.NSW.Bfres;
using Syroot.NintenTools.NSW.Bfres.Helpers;
using OpenTK;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Rendering;
using WeifenLuo.WinFormsUI.Docking;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library.Forms;
using ResU = Syroot.NintenTools.Bfres;
using ResUGX2 = Syroot.NintenTools.Bfres.GX2;
using ResGFX = Syroot.NintenTools.NSW.Bfres.GFX;
using FirstPlugin;
namespace Bfres.Structs
{
public class Misc
{
public static List<string> HackyTextureList = new List<string>(new string[] {
"Alb", "alb", "Base", "base", "bonbon.167300917","Eye.00","EyeIce.00", "FaceDummy", "Eye01.17", "Dee.00",
"rainbow.758540574", "Mucus._1700670200", "Eye.11", "CapTail00","eye.0","pallet_texture","Mark.930799313","InEye.1767598300","Face.00",
"ThunderHair_Thunder_BaseColor.1751853236","FireHair_Thunder_BaseColor._162539711","IceHair_Thunder_BaseColor.674061150","BodyEnemy.1866226988",
"Common_Scroll01._13827715"
});
}
public class ResourceFile : TreeNodeFile
{
public BFRESRender BFRESRender;
public TreeNode TextureFolder = new TreeNode("Textures");
public ResourceFile(IFileFormat handler)
{
ImageKey = "bfres";
SelectedImageKey = "bfres";
FileHandler = handler;
ContextMenu = new ContextMenu();
MenuItem save = new MenuItem("Save");
ContextMenu.MenuItems.Add(save);
save.Click += Save;
MenuItem newMenu = new MenuItem("New");
MenuItem import = new MenuItem("Import");
// ContextMenu.MenuItems.Add(newMenu);
// ContextMenu.MenuItems.Add(import);
MenuItem rename = new MenuItem("Rename");
ContextMenu.MenuItems.Add(rename);
rename.Click += Rename;
MenuItem remove = new MenuItem("Remove");
ContextMenu.MenuItems.Add(remove);
remove.Click += Remove;
if (Parent == null)
remove.Enabled = false;
if (BFRES.IsWiiU)
{
}
else
{
MenuItem model = new MenuItem("Model");
MenuItem fska = new MenuItem("Skeletal Animation");
MenuItem fmaa = new MenuItem("Material Animation");
MenuItem bonevis = new MenuItem("Bone Visual Animation");
MenuItem shape = new MenuItem("Shape Animation");
MenuItem scene = new MenuItem("Scene Animation");
MenuItem embedded = new MenuItem("Embedded File");
MenuItem texture = new MenuItem("Texture File");
texture.Click += NewTextureFile;
newMenu.MenuItems.Add(model);
newMenu .MenuItems.Add(fska);
newMenu.MenuItems.Add(fmaa);
newMenu.MenuItems.Add(bonevis);
newMenu.MenuItems.Add(shape);
newMenu.MenuItems.Add(scene);
newMenu.MenuItems.Add(embedded);
newMenu.MenuItems.Add(texture);
MenuItem importmodel = new MenuItem("Model");
MenuItem importfska = new MenuItem("Skeletal Animation");
MenuItem importfmaa = new MenuItem("Material Animation");
MenuItem importbonevis = new MenuItem("Bone Visual Animation");
MenuItem importshape = new MenuItem("Shape Animation");
MenuItem importscene = new MenuItem("Scene Animation");
MenuItem importembedded = new MenuItem("Embedded File");
MenuItem importtexture = new MenuItem("Texture File");
import.MenuItems.Add(importmodel);
import.MenuItems.Add(importfska);
import.MenuItems.Add(importfmaa);
import.MenuItems.Add(importbonevis);
import.MenuItems.Add(importshape);
import.MenuItems.Add(importscene);
import.MenuItems.Add(importembedded);
import.MenuItems.Add(importtexture);
}
}
public override void OnClick(TreeView treeView)
{
//If has models
if (Nodes.ContainsKey("FMDLFolder"))
{
if (Nodes["FMDLFolder"].Nodes.ContainsKey("FshpFolder"))
{
}
LibraryGUI.Instance.LoadViewport(Viewport.Instance);
Viewport.Instance.gL_ControlModern1.MainDrawable = BFRESRender;
BFRESRender.UpdateVertexData();
}
}
public void Load(ResU.ResFile resFile)
{
Text = resFile.Name;
if (resFile.Models.Count > 0)
Nodes.Add(new FmdlFolder());
if (resFile.Textures.Count > 0)
AddFTEXTextures(resFile);
if (resFile.SkeletalAnims.Count > 0)
AddSkeletonAnims(resFile);
if (resFile.ShaderParamAnims.Count > 0)
Nodes.Add(new FshaFolder());
if (resFile.ColorAnims.Count > 0)
Nodes.Add(new FshaColorFolder());
if (resFile.TexSrtAnims.Count > 0)
Nodes.Add(new TexSrtFolder());
if (resFile.TexPatternAnims.Count > 0)
Nodes.Add(new TexPatFolder());
if (resFile.ShapeAnims.Count > 0)
Nodes.Add(new FshpaFolder());
if (resFile.BoneVisibilityAnims.Count > 0)
Nodes.Add(new FbnvFolder());
if (resFile.SceneAnims.Count > 0)
Nodes.Add(new FscnFolder());
if (resFile.ExternalFiles.Count > 0)
Nodes.Add(new EmbeddedFilesFolder());
foreach (var anim in resFile.ShaderParamAnims)
Nodes["FSHA"].Nodes.Add(anim.Key);
foreach (var anim in resFile.ColorAnims)
Nodes["FSHAColor"].Nodes.Add(anim.Key);
foreach (var anim in resFile.TexSrtAnims)
Nodes["TEXSRT"].Nodes.Add(anim.Key);
foreach (var anim in resFile.TexPatternAnims)
Nodes["TEXPAT"].Nodes.Add(anim.Key);
int ext = 0;
foreach (var extfile in resFile.ExternalFiles)
{
string Name = extfile.Key;
FileReader f = new FileReader(extfile.Value.Data);
string Magic = f.ReadMagic(0, 4);
if (Magic == "FSHA")
{
Nodes["EXT"].Nodes.Add(new BfshaFileData(extfile.Value.Data, Name));
}
else
Nodes["EXT"].Nodes.Add(new ExternalFileData(extfile.Value.Data, Name));
f.Dispose();
f.Close();
ext++;
}
}
public void Load(ResFile resFile)
{
Text = resFile.Name;
UpdateTree(resFile);
foreach (MaterialAnim anim in resFile.MaterialAnims)
Nodes["FMAA"].Nodes.Add(anim.Name);
foreach (ShapeAnim anim in resFile.ShapeAnims)
Nodes["FSHPA"].Nodes.Add(anim.Name);
foreach (VisibilityAnim anim in resFile.BoneVisibilityAnims)
Nodes["FBNV"].Nodes.Add(anim.Name);
foreach (SceneAnim anim in resFile.SceneAnims)
Nodes["FSCN"].Nodes.Add(anim.Name);
int ext = 0;
foreach (ExternalFile extfile in resFile.ExternalFiles)
{
string Name = resFile.ExternalFileDict.GetKey(ext);
FileReader f = new FileReader(extfile.Data);
string Magic = f.ReadMagic(0, 4);
if (Magic == "BNTX")
{
BNTX bntx = new BNTX();
bntx.Data = extfile.Data;
bntx.FileName = Name;
bntx.Load();
bntx.IFileInfo.InArchive = true;
Nodes["EXT"].Nodes.Add(bntx.EditorRoot);
}
else if (Magic == "FSHA")
{
Nodes["EXT"].Nodes.Add(new BfshaFileData(extfile.Data, Name));
}
else
Nodes["EXT"].Nodes.Add(new ExternalFileData(extfile.Data, Name));
f.Dispose();
f.Close();
ext++;
}
}
private void NewTextureFile(object sender, EventArgs args)
{
string Name = "textures";
for (int i = 0; i < BFRESRender.resFile.ExternalFiles.Count; i++)
{
if (BFRESRender.resFile.ExternalFileDict.GetKey(i) == Name)
Name = Name + i;
}
if (!Nodes.ContainsKey("EXT"))
{
Nodes.Add(new EmbeddedFilesFolder());
}
BNTX bntx = new BNTX();
bntx.Data = new byte[0];
BinaryTextureContainer bntxTreeNode = new BinaryTextureContainer(new byte[0], "textures", BFRESRender.resFile.Name);
Nodes["EXT"].Nodes.Add(bntxTreeNode);
}
private void NewEmbeddedFile(object sender, EventArgs args)
{
}
private void Save(object sender, EventArgs args)
{
((BFRES)FileHandler).SaveFile();
}
private void Rename(object sender, EventArgs args)
{
RenameDialog dialog = new RenameDialog();
dialog.SetString(Text);
if (dialog.ShowDialog() == DialogResult.OK)
{
Text = dialog.textBox1.Text;
}
}
private void Remove(object sender, EventArgs args)
{
BFRESRender.DisposeFile();
}
private void UpdateTree(ResFile resFile)
{
if (resFile.Models.Count > 0)
Nodes.Add(new FmdlFolder());
if (resFile.SkeletalAnims.Count > 0)
AddSkeletonAnims(resFile);
if (resFile.MaterialAnims.Count > 0)
Nodes.Add(new FmmaFolder());
if (resFile.ShapeAnims.Count > 0)
Nodes.Add(new FshpaFolder());
if (resFile.BoneVisibilityAnims.Count > 0)
Nodes.Add(new FbnvFolder());
if (resFile.SceneAnims.Count > 0)
Nodes.Add(new FscnFolder());
if (resFile.ExternalFiles.Count > 0)
Nodes.Add(new EmbeddedFilesFolder());
}
private void AddFTEXTextures(ResU.ResFile resFile)
{
FTEXContainer ftexContainer = new FTEXContainer();
foreach (ResU.Texture tex in resFile.Textures.Values)
{
string TextureName = tex.Name;
FTEX texture = new FTEX();
texture.Read(tex);
ftexContainer.Nodes.Add(texture);
ftexContainer.Textures.Add(texture.Text, texture);
}
PluginRuntime.ftexContainers.Add(ftexContainer);
Nodes.Add(ftexContainer);
}
private void AddSkeletonAnims(ResU.ResFile resFile)
{
FskaFolder FSKA = new FskaFolder();
FSKA.LoadAnimations(resFile, BFRESRender);
Nodes.Add(FSKA);
}
private void AddSkeletonAnims(ResFile resFile)
{
FskaFolder FSKA = new FskaFolder();
FSKA.LoadAnimations(resFile, BFRESRender);
Nodes.Add(FSKA);
}
}
public class FshpaFolder : TreeNodeCustom
{
public FshpaFolder()
{
Text = "Shape Animations";
Name = "FSHPA";
}
public override void OnClick(TreeView treeView)
{
FormLoader.LoadEditor(this, Text);
}
}
}

View file

@ -0,0 +1,223 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Syroot.NintenTools.NSW.Bfres;
using Switch_Toolbox.Library;
using ResU = Syroot.NintenTools.Bfres;
using Switch_Toolbox.Library.Animations;
namespace Bfres.Structs
{
public class CurveHelper
{
public static AnimCurveFrameType GetFrameType(uint FrameCount)
{
if (FrameCount < byte.MaxValue) return AnimCurveFrameType.Byte;
if (FrameCount < Int16.MaxValue) return AnimCurveFrameType.Decimal10x5;
else return AnimCurveFrameType.Single;
}
public static AnimCurveKeyType GetKeyType(float Value)
{
if (Value < byte.MaxValue) return AnimCurveKeyType.SByte;
if (Value < Int16.MaxValue) return AnimCurveKeyType.Int16;
else return AnimCurveKeyType.Single;
}
public static Animation.KeyGroup CreateTrackWiiU(ResU.AnimCurve animCurve)
{
Animation.KeyGroup track = new Animation.KeyGroup();
track.AnimDataOffset = animCurve.AnimDataOffset;
track.Scale = animCurve.Scale;
track.Offset = animCurve.Offset;
track.StartFrame = animCurve.StartFrame;
track.EndFrame = animCurve.EndFrame;
track.Delta = animCurve.Delta;
float tanscale = animCurve.Delta;
if (tanscale == 0)
tanscale = 1;
if (animCurve.Scale == 0)
animCurve.Scale = 1;
for (int i = 0; i < (ushort)animCurve.Frames.Length; i++)
{
switch (animCurve.CurveType)
{
case ResU.AnimCurveType.Cubic: //4 elements are stored for cubic
track.InterpolationType = InterpolationType.HERMITE;
track.Keys.Add(new Animation.KeyFrame()
{
IsKeyed = true,
InterType = InterpolationType.HERMITE,
Frame = (int)animCurve.Frames[i],
Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value2 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
Value3 = animCurve.Offset + (animCurve.Keys[i, 2] * animCurve.Scale),
Value4 = animCurve.Offset + (animCurve.Keys[i, 3] * animCurve.Scale),
});
break;
case ResU.AnimCurveType.Linear: //2 elements are stored for linear
track.InterpolationType = InterpolationType.LINEAR;
track.Keys.Add(new Animation.KeyFrame()
{
IsKeyed = true,
InterType = InterpolationType.LINEAR,
Frame = (int)animCurve.Frames[i],
Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value2 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
});
break;
case ResU.AnimCurveType.StepInt: //1 element are stored for step
track.InterpolationType = InterpolationType.STEP;
track.Keys.Add(new Animation.KeyFrame()
{
IsKeyed = true,
InterType = InterpolationType.STEP,
Frame = (int)animCurve.Frames[i],
Value = (int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale,
Value1 = (int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale,
});
break;
default:
throw new Exception("Unsupported anim type!");
}
}
return track;
}
public static BooleanKeyGroup CreateBooleanTrackWiiU(ResU.AnimCurve animCurve)
{
BooleanKeyGroup track = new BooleanKeyGroup();
track.AnimDataOffset = animCurve.AnimDataOffset;
track.Scale = animCurve.Scale;
track.Offset = animCurve.Offset;
track.StartFrame = animCurve.StartFrame;
track.EndFrame = animCurve.EndFrame;
track.Delta = animCurve.Delta;
for (int i = 0; i < (ushort)animCurve.Frames.Length; i++)
{
switch (animCurve.CurveType)
{
case ResU.AnimCurveType.StepBool: //1 element are stored for step
track.Keys.Add(new BooleanKeyFrame()
{
IsKeyed = true,
InterType = InterpolationType.STEPBOOL,
Frame = (int)animCurve.Frames[i],
Visible = animCurve.KeyStepBoolData[i],
});
break;
default:
throw new Exception("Unsupported anim type!");
}
}
return track;
}
public static BooleanKeyGroup CreateBooleanTrack(AnimCurve animCurve)
{
BooleanKeyGroup track = new BooleanKeyGroup();
track.AnimDataOffset = animCurve.AnimDataOffset;
track.Scale = animCurve.Scale;
track.Offset = animCurve.Offset;
track.StartFrame = animCurve.StartFrame;
track.EndFrame = animCurve.EndFrame;
track.Delta = animCurve.Delta;
for (int i = 0; i < (ushort)animCurve.Frames.Length; i++)
{
switch (animCurve.CurveType)
{
case AnimCurveType.StepBool: //1 element are stored for step
track.Keys.Add(new BooleanKeyFrame()
{
IsKeyed = true,
InterType = InterpolationType.STEPBOOL,
Frame = (int)animCurve.Frames[i],
Visible = animCurve.KeyStepBoolData[i],
});
break;
default:
throw new Exception("Unsupported anim type!");
}
}
return track;
}
public static Animation.KeyGroup CreateTrack(AnimCurve animCurve)
{
Animation.KeyGroup track = new Animation.KeyGroup();
track.AnimDataOffset = animCurve.AnimDataOffset;
track.Scale = animCurve.Scale;
track.Offset = animCurve.Offset;
track.StartFrame = animCurve.StartFrame;
track.EndFrame = animCurve.EndFrame;
track.Delta = animCurve.Delta;
float tanscale = animCurve.Delta;
if (tanscale == 0)
tanscale = 1;
if (animCurve.Scale == 0)
animCurve.Scale = 1;
for (int i = 0; i < (ushort)animCurve.Frames.Length; i++)
{
switch (animCurve.CurveType)
{
case AnimCurveType.Cubic: //4 elements are stored for cubic
track.InterpolationType = InterpolationType.HERMITE;
track.Keys.Add(new Animation.KeyFrame()
{
IsKeyed = true,
InterType = InterpolationType.HERMITE,
Frame = (int)animCurve.Frames[i],
Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value1 = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value2 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
Value3 = animCurve.Offset + (animCurve.Keys[i, 2] * animCurve.Scale),
Value4 = animCurve.Offset + (animCurve.Keys[i, 3] * animCurve.Scale),
});
break;
case AnimCurveType.Linear: //2 elements are stored for linear
track.InterpolationType = InterpolationType.LINEAR;
track.Keys.Add(new Animation.KeyFrame()
{
IsKeyed = true,
InterType = InterpolationType.LINEAR,
Frame = (int)animCurve.Frames[i],
Value = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value1 = animCurve.Offset + (animCurve.Keys[i, 0] * animCurve.Scale),
Value2 = animCurve.Offset + (animCurve.Keys[i, 1] * animCurve.Scale),
});
break;
case AnimCurveType.StepInt: //1 element are stored for step
track.InterpolationType = InterpolationType.STEP;
track.Keys.Add(new Animation.KeyFrame()
{
IsKeyed = true,
InterType = InterpolationType.STEP,
Frame = (int)animCurve.Frames[i],
Value = (int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale,
Value1 = (int)animCurve.Offset + (int)animCurve.Keys[i, 0] * animCurve.Scale,
});
break;
default:
throw new Exception("Unsupported anim type!");
}
}
return track;
}
}
}

View file

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Syroot.NintenTools.NSW.Bfres;
using Syroot.NintenTools.NSW.Bfres.Helpers;
using OpenTK;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Rendering;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library.Forms;
using FirstPlugin;
namespace Bfres.Structs
{
public class Misc
{
public static List<string> HackyTextureList = new List<string>(new string[] {
"Alb", "alb", "Base", "base", "bonbon.167300917","Eye.00","EyeIce.00", "FaceDummy", "Eye01.17", "Dee.00",
"rainbow.758540574", "Mucus._1700670200", "Eye.11", "CapTail00","eye.0","pallet_texture","Mark.930799313","InEye.1767598300","Face.00",
"ThunderHair_Thunder_BaseColor.1751853236","FireHair_Thunder_BaseColor._162539711","IceHair_Thunder_BaseColor.674061150","BodyEnemy.1866226988",
"Common_Scroll01._13827715"
});
}
}

View file

@ -0,0 +1,60 @@
using System;
using Switch_Toolbox.Library;
using System.Windows.Forms;
using FirstPlugin;
using Switch_Toolbox.Library.NodeWrappers;
using Switch_Toolbox.Library.Forms;
namespace Bfres.Structs
{
public class ExternalFileData : STGenericWrapper
{
public override string ExportFilter => "All files (*.*)|*.*";
//Format to attach
public IFileFormat FileFormat;
public byte[] Data;
public ExternalFileData(string name, byte[] data)
{
ImageKey = "folder";
Text = name;
Data = data;
CanDelete = true;
CanRename = true;
CanReplace = true;
CanExport = true;
}
public override void OnClick(TreeView treeview) {
UpdateEditor();
}
private void UpdateEditor()
{
HexEditor editor = (HexEditor)LibraryGUI.Instance.GetActiveContent(typeof(HexEditor));
if (editor == null)
{
editor = new HexEditor();
editor.Dock = DockStyle.Fill;
LibraryGUI.Instance.LoadEditor(editor);
}
editor.Text = Text;
editor.LoadData(Data);
}
public override void Replace(string FileName)
{
Data = System.IO.File.ReadAllBytes(FileName);
UpdateEditor();
}
public override void Export(string FileName)
{
System.IO.File.WriteAllBytes(FileName, Data);
}
}
}

View file

@ -0,0 +1,726 @@
using System;
using System.Text;
using System.Collections.Generic;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using FirstPlugin;
using Syroot.NintenTools.NSW.Bfres;
using FirstPlugin.Forms;
using Switch_Toolbox.Library.Animations;
namespace Bfres.Structs
{
public class FMAA : MaterialAnimation
{
private static readonly string ShaderParamAnimType = "_fsp";
private static readonly string ShaderParamAnimType2= "_sp";
private static readonly string TexturePatternAnimType = "_ftp";
private static readonly string TexturePatternAnimType2 = "_tp";
private static readonly string TextureSrtAnimType = "_fts";
private static readonly string TextureSrtAnimType2 = "_ts";
private static readonly string ColorAnimType = "_fcl";
private static readonly string ColorAnimType2 = "_cl";
private static readonly string VisibiltyAnimType = "_fvm";
private static readonly string VisibiltyAnimType2 = "_vm";
public static bool IsShaderParamAnimation(string name) {
return name.Contains(ShaderParamAnimType) ||
name.Contains(ShaderParamAnimType2);
}
public static bool IsSRTAnimation(string name){
return name.Contains(TextureSrtAnimType) ||
name.Contains(TextureSrtAnimType2);
}
public static bool IsTexturePattern(string name) {
return name.Contains(TexturePatternAnimType) ||
name.Contains(TexturePatternAnimType2);
}
public static bool IsColorAnimation(string name) {
return name.Contains(ColorAnimType) ||
name.Contains(ColorAnimType2);
}
public static bool IsVisibiltyAnimation(string name) {
return name.Contains(VisibiltyAnimType) ||
name.Contains(VisibiltyAnimType2);
}
public class MaterialAnimEntry : Material
{
public FMAA matAnimWrapper;
public MaterialAnimData MaterialAnimData;
public MaterialAnimEntry(string name) : base(name)
{
}
public void LoadMaterial(MaterialAnimData data, FMAA materialAnimation)
{
MaterialAnimData = data;
matAnimWrapper = materialAnimation;
}
public void CreateSampler(string Name, bool IsConstant)
{
var mat = MaterialAnimData;
var SamplerInfo = new TexturePatternAnimInfo();
if (IsConstant)
{
SamplerInfo.BeginConstant = (ushort)mat.Constants.Count;
SamplerInfo.CurveIndex = (ushort)65535;
}
else
{
SamplerInfo.BeginConstant = (ushort)65535;
SamplerInfo.CurveIndex = (uint)mat.Curves.Count;
}
mat.TexturePatternAnimInfos.Add(SamplerInfo);
BfresSamplerAnim sampler = new BfresSamplerAnim(SamplerInfo.Name, matAnimWrapper, this);
Samplers.Add(sampler);
}
public MaterialAnimData SaveData()
{
MaterialAnimData.Name = Text;
return MaterialAnimData;
}
}
public void UpdateMaterialBinds()
{
MaterialAnim.TextureBindArray = new List<long>();
ushort[] binds = new ushort[MaterialAnim.MaterialAnimDataList.Count];
for (int i = 0; i < binds.Length; i++)
binds[i] = ushort.MaxValue;
for (int i = 0; i < MaterialAnim.TextureNames.Count; i++)
MaterialAnim.TextureBindArray.Add(- 1);
MaterialAnim.BindIndices = binds;
}
public override void UpdateAnimationData()
{
MaterialAnim.FrameCount = FrameCount;
MaterialAnim.TextureNames = Textures;
}
public void SaveAnimData()
{
if (!IsEdited)
return;
MaterialAnim.FrameCount = FrameCount;
MaterialAnim.TextureNames = Textures;
int TexturePatternCurveIndex = 0;
int ParamCurveIndex = 0;
MaterialAnimData data = new MaterialAnimData();
MaterialAnim.MaterialAnimDataList.Add(data);
foreach (MaterialAnimEntry mat in Materials)
{
mat.MaterialAnimData = new MaterialAnimData();
mat.MaterialAnimData.Name = mat.Text;
//Set default indices as unused for now
mat.MaterialAnimData.BeginVisalConstantIndex = -1;
mat.MaterialAnimData.ShaderParamCurveIndex = -1;
mat.MaterialAnimData.TexturePatternCurveIndex = -1;
mat.MaterialAnimData.VisalCurveIndex = -1;
mat.MaterialAnimData.VisualConstantIndex = -1;
//Load our first curve index if a sampler or param has one
SavePatternInfos(data, mat, TexturePatternCurveIndex);
SaveParamInfos(data, mat, ParamCurveIndex);
}
UpdateMaterialBinds();
}
private void SavePatternInfos(MaterialAnimData data, Material mat, int TexturePatternCurveIndex)
{
bool SetBeginCurve = false;
foreach (var sampler in mat.Samplers)
{
//If constant, create a constant instance with the first value set
if (sampler.group.Constant)
{
AnimConstant animConstant = new AnimConstant();
animConstant.AnimDataOffset = 0;
animConstant.Value = sampler.group.GetValue(0);
data.Constants.Add(animConstant);
}
else if (sampler.group.Keys.Count > 0)
{
//If a sampler is not constant and uses curve data, then we need to set our begin curve index
if (!SetBeginCurve)
{
data.TexturePatternCurveIndex += TexturePatternCurveIndex;
data.BeginVisalConstantIndex += 0; //This is usually 0 so set it
SetBeginCurve = true;
}
//Create a curve to store all the index data in for each frame
AnimCurve curve = new AnimCurve();
curve.AnimDataOffset = 0;
//Set our data types. Pattern and visibilty are always the same type
if (AnimType == AnimationType.TexturePattern)
curve.CurveType = AnimCurveType.StepInt;
else if (AnimType == AnimationType.Visibilty)
curve.CurveType = AnimCurveType.StepBool;
else
{
if (sampler.group.InterpolationType == InterpolationType.HERMITE)
curve.CurveType = AnimCurveType.Cubic;
if (sampler.group.InterpolationType == InterpolationType.LINEAR)
curve.CurveType = AnimCurveType.Linear;
if (sampler.group.InterpolationType == InterpolationType.STEP)
curve.CurveType = AnimCurveType.StepInt;
if (sampler.group.InterpolationType == InterpolationType.STEPBOOL)
curve.CurveType = AnimCurveType.StepBool;
}
curve.Delta = 0;
curve.EndFrame = FrameCount;
curve.StartFrame = 0;
curve.FrameType = AnimCurveFrameType.Byte;
curve.Scale = 1;
curve.Offset = 0;
List<float> Frames = new List<float>();
List<float> Keys = new List<float>();
for (int frame = 0; frame < sampler.group.Keys.Count; frame++)
{
float currentIndex = sampler.group.GetValue(frame);
if (frame > 0)
{
float previousIndex = sampler.group.GetValue(frame - 1);
if (currentIndex != previousIndex)
{
//Add key frame if texture not loaded previously
Frames.Add(frame);
Keys.Add(currentIndex);
}
}
else
{
//Add the first key frame value. We would add base values here but switch has none
Frames.Add(frame);
Keys.Add(currentIndex);
}
}
for (int i = 0; i <Keys.Count; i++)
{
curve.Keys[i, 0] = Keys[i];
}
curve.Frames = Frames.ToArray();
TexturePatternCurveIndex += 1;
}
}
}
private void SaveParamInfos(MaterialAnimData data, Material mat, int ParamCurveIndex)
{
foreach (var param in mat.Params)
{
//Set our begin curve index
bool SetBeginCurve = false;
if (!SetBeginCurve)
{
data.ShaderParamCurveIndex += ParamCurveIndex;
data.BeginVisalConstantIndex += 0; //This is usually 0 so set it
SetBeginCurve = true;
}
foreach (var value in param.Values)
{
if (value.Constant)
{
AnimConstant animConstant = new AnimConstant();
animConstant.AnimDataOffset = 0;
animConstant.Value = value.GetValue(0); //Set our constant value
data.Constants.Add(animConstant);
}
else if (value.Keys.Count > 0) //Else create curves for each param value
{
//If constant, create a constant instance with the first value set
AnimCurve curve = new AnimCurve();
curve.AnimDataOffset = value.AnimDataOffset;
curve.Scale = value.Scale;
curve.Offset = value.Offset;
data.Curves.Add(curve);
}
}
}
}
public void UpdateMaterials(Material mat)
{
}
private string GetString(string Name)
{
StringBuilder builder = new StringBuilder(Name);
builder.Replace(ShaderParamAnimType, "");
builder.Replace(TexturePatternAnimType, "");
builder.Replace(TextureSrtAnimType, "");
builder.Replace(ColorAnimType, "");
builder.Replace(VisibiltyAnimType, "");
return builder.ToString();
}
public string SetName()
{
Text = GetString(Text); //Remove any extension just in case
//Add extension to the end of the string based on type
if (AnimType == AnimationType.Color)
Text += ColorAnimType;
else if (AnimType == AnimationType.ShaderParam)
Text += ShaderParamAnimType;
else if (AnimType == AnimationType.TexturePattern)
Text += TexturePatternAnimType;
else if (AnimType == AnimationType.TextureSrt)
Text += TextureSrtAnimType;
else if (AnimType == AnimationType.Visibilty)
Text += VisibiltyAnimType;
else
Text += ShaderParamAnimType;
MaterialAnim.Name = Text;
return Text;
}
public BFRESRender BFRESRender;
public MaterialAnim MaterialAnim;
public FMAA()
{
Initialize();
}
public void Initialize()
{
ImageKey = "materialAnim";
SelectedImageKey = "materialAnim";
ContextMenuStrip = new ContextMenuStrip();
LoadFileMenus(false);
}
protected void NewAction(object sender, EventArgs e) { NewMaterialAnim(); }
public void NewMaterialAnim()
{
var mat = new MaterialAnimEntry("NewMaterialTarget");
mat.LoadMaterial(new MaterialAnimData() { Name = mat.Text }, this);
Materials.Add(mat);
}
public override void OnClick(TreeView treeView) => UpdateEditor();
public void UpdateEditor(){
((BFRES)Parent.Parent.Parent).LoadEditors(this);
}
public ResFile GetResFile()
{
return ((BFRESGroupNode)Parent).GetResFile();
}
public FMAA(MaterialAnim anim, AnimationType type) { LoadAnim(anim); AnimType = type; }
private void LoadAnim(MaterialAnim anim)
{
Initialize();
MaterialAnim = anim;
FrameCount = MaterialAnim.FrameCount;
Text = GetString(anim.Name);
if (anim.TextureNames != null)
{
foreach (var name in anim.TextureNames)
Textures.Add(name);
}
foreach (var matanim in anim.MaterialAnimDataList)
{
var mat = new MaterialAnimEntry(matanim.Name);
mat.MaterialAnimData = matanim;
Materials.Add(mat);
foreach (var param in matanim.ParamAnimInfos)
{
FSHU.BfresParamAnim paramInfo = new FSHU.BfresParamAnim(param.Name);
mat.Params.Add(paramInfo);
paramInfo.Type = AnimationType.ShaderParam;
//There is no better way to determine if the param is a color type afaik
if (anim.Name.Contains(ColorAnimType) || param.Name.Contains("color"))
paramInfo.Type = AnimationType.Color;
else if (anim.Name.Contains(TextureSrtAnimType))
paramInfo.Type = AnimationType.TexturePattern;
else if (anim.Name.Contains(ShaderParamAnimType))
paramInfo.Type = AnimationType.ShaderParam;
//Get constant anims
for (int constant = 0; constant < param.ConstantCount; constant++)
{
int index = constant + param.BeginConstant;
Animation.KeyGroup keyGroup = new Animation.KeyGroup();
keyGroup.Keys.Add(new Animation.KeyFrame()
{
InterType = InterpolationType.CONSTANT,
Frame = 0,
Value = matanim.Constants[index].Value,
});
paramInfo.Values.Add(new Animation.KeyGroup()
{
AnimDataOffset = matanim.Constants[index].AnimDataOffset,
Keys = keyGroup.Keys,
});
}
for (int curve = 0; curve < param.FloatCurveCount + param.IntCurveCount; curve++)
{
int index = curve + param.BeginCurve;
Animation.KeyGroup keyGroup = CurveHelper.CreateTrack(matanim.Curves[index]);
keyGroup.AnimDataOffset = matanim.Curves[index].AnimDataOffset;
paramInfo.Values.Add(new Animation.KeyGroup()
{
AnimDataOffset = keyGroup.AnimDataOffset,
Keys = keyGroup.Keys,
});
}
}
foreach (TexturePatternAnimInfo SamplerInfo in matanim.TexturePatternAnimInfos)
{
BfresSamplerAnim sampler = new BfresSamplerAnim(SamplerInfo.Name, this, mat);
mat.Samplers.Add(sampler);
int textureIndex = 0;
uint animOffset = 0;
if (SamplerInfo.BeginConstant != 65535)
{
animOffset = matanim.Constants[SamplerInfo.BeginConstant].AnimDataOffset;
textureIndex = matanim.Constants[SamplerInfo.BeginConstant].Value;
var group = new Animation.KeyGroup();
group.AnimDataOffset = animOffset;
group.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = textureIndex });
group.Constant = true;
sampler.group = group;
}
if (SamplerInfo.CurveIndex != 65535)
{
int index = (int)SamplerInfo.CurveIndex;
Animation.KeyGroup keyGroup = CurveHelper.CreateTrack(matanim.Curves[index]);
keyGroup.AnimDataOffset = matanim.Curves[index].AnimDataOffset;
sampler.group = new KeyGroup()
{
AnimDataOffset = keyGroup.AnimDataOffset,
Keys = keyGroup.Keys,
};
}
}
}
}
public class BfresSamplerAnim : Material.Sampler
{
FMAA MatAnimWrapper;
MaterialAnimEntry MatWrapper;
public BfresSamplerAnim(string Name, FMAA materialAnimation, MaterialAnimEntry material)
{
MatWrapper = material;
MatAnimWrapper = materialAnimation;
Text = Name;
}
public override string GetActiveTextureName(int frame)
{
uint val = (uint)group.GetValue(frame);
return MatAnimWrapper.Textures[(int)val];
}
public void AddKeyFrame(string TextureName, int Frame, bool IsConstant = false)
{
group.Constant = IsConstant;
var MatAnim = MatAnimWrapper.MaterialAnim;
//Add the texture if it does not exist for both wrapper and bfres itself
if (!MatAnim.TextureNames.Contains(TextureName))
MatAnim.TextureNames.Add(TextureName);
if (!MatAnimWrapper.Textures.Contains(TextureName))
MatAnimWrapper.Textures.Add(TextureName);
//Set our index
int index = MatAnimWrapper.Textures.IndexOf(TextureName);
//For non constants we load a curve
if (!group.Constant)
{
}
}
private AnimCurve CreateAnimCurve()
{
//Create empty curve
AnimCurve curve = new AnimCurve();
curve.Offset = 0;
curve.StartFrame = 0;
curve.EndFrame = MatAnimWrapper.FrameCount;
curve.CurveType = AnimCurveType.StepInt;
curve.AnimDataOffset = 0;
curve.Scale = 1;
//Start with sbyte. Increase only if index is > 255
curve.KeyType = AnimCurveKeyType.SByte;
//Set by frame count
curve.FrameType = CurveHelper.GetFrameType((uint)MatAnimWrapper.FrameCount);
return curve;
}
public override STGenericTexture GetActiveTexture(int frame)
{
uint val = (uint)group.GetValue(frame);
foreach (var bntx in PluginRuntime.bntxContainers)
{
try
{
string name = MatAnimWrapper.Textures[(int)val];
if (bntx.Textures.ContainsKey(name))
return bntx.Textures[name];
}
catch
{
throw new Exception("Index out of range " + val);
}
}
return null;
}
}
public override void NextFrame(Viewport viewport)
{
if (Frame >= FrameCount) return;
//Loop through each drawable bfres in the active viewport to display the anim
foreach (var drawable in viewport.scene.objects)
{
if (drawable is BFRESRender)
LoadMaterialAnimation(((BFRESRender)drawable).models);
}
}
private void LoadMaterialAnimation(List<FMDL> models)
{
//Loop through each FMDL's materials until it matches the material anim
foreach (var model in models)
{
foreach (Material matAnim in Materials)
{
if (model.materials.ContainsKey(matAnim.Text))
EditMaterial(model.materials[matAnim.Text], matAnim);
}
}
}
private void EditMaterial(FMAT material, Material matAnim)
{
//Alright material animations have a total of 5 types.
//SRT (type of shader param)
//Color (type of shader param)
//Shader param
//Visibily animation
//Texture pattern animation
SetMaterialVisualAnimation(material, matAnim);
SetShaderParamAnimation(material, matAnim);
SetTextureAnimation(material, matAnim);
}
private void SetMaterialVisualAnimation(FMAT material, Material matAnim)
{
}
private void SetShaderParamAnimation(FMAT material, Material matAnim)
{
if (matAnim.Params.Count == 0)
return;
//Loop through param list for shader param anims
//These store a list of values with offsets to the value
//Then we'll update the active texture
foreach (FSHU.BfresParamAnim paramAnim in matAnim.Params)
{
if (material.matparam.ContainsKey(paramAnim.Text))
{
//First we get the active param that we want to alter
BfresShaderParam prm = material.matparam[paramAnim.Text];
BfresShaderParam animatedprm = new BfresShaderParam();
if (!material.animatedMatParams.ContainsKey(prm.Name))
material.animatedMatParams.Add(prm.Name, animatedprm);
animatedprm.Name = prm.Name;
animatedprm.ValueUint = prm.ValueUint;
animatedprm.ValueBool = prm.ValueBool;
animatedprm.ValueFloat = prm.ValueFloat;
animatedprm.ValueSrt2D = prm.ValueSrt2D;
animatedprm.ValueSrt3D = prm.ValueSrt3D;
animatedprm.ValueTexSrt = prm.ValueTexSrt;
animatedprm.ValueTexSrtEx = prm.ValueTexSrtEx;
foreach (var group in paramAnim.Values)
{
//The offset determines the value starting from 0.
int index = 0;
if (prm.ValueFloat != null)
{
if (group.AnimDataOffset != 0)
index = (int)group.AnimDataOffset / sizeof(float);
animatedprm.ValueFloat[index] = group.GetValue(Frame);
}
if (prm.ValueInt != null)
{
}
if (prm.ValueUint != null)
{
}
if (prm.ValueBool != null)
{
}
if (prm.Type == ShaderParamType.Srt3D)
{
if (group.AnimDataOffset == 0) prm.ValueSrt3D.Scaling.X = group.GetValue(Frame);
if (group.AnimDataOffset == 4) prm.ValueSrt3D.Scaling.Y = group.GetValue(Frame);
if (group.AnimDataOffset == 8) prm.ValueSrt3D.Scaling.Z = group.GetValue(Frame);
if (group.AnimDataOffset == 12) prm.ValueSrt3D.Rotation.X = group.GetValue(Frame);
if (group.AnimDataOffset == 16) prm.ValueSrt3D.Rotation.Y = group.GetValue(Frame);
if (group.AnimDataOffset == 20) prm.ValueSrt3D.Rotation.Z = group.GetValue(Frame);
if (group.AnimDataOffset == 24) prm.ValueSrt3D.Translation.X = group.GetValue(Frame);
if (group.AnimDataOffset == 28) prm.ValueSrt3D.Translation.Y = group.GetValue(Frame);
if (group.AnimDataOffset == 32) prm.ValueSrt3D.Translation.Z = group.GetValue(Frame);
}
if (prm.Type == ShaderParamType.Srt2D)
{
if (group.AnimDataOffset == 0) prm.ValueSrt2D.Scaling.X = group.GetValue(Frame);
if (group.AnimDataOffset == 4) prm.ValueSrt2D.Scaling.Y = group.GetValue(Frame);
if (group.AnimDataOffset == 8) prm.ValueSrt2D.Rotation = group.GetValue(Frame);
if (group.AnimDataOffset == 12) prm.ValueSrt2D.Translation.X = group.GetValue(Frame);
if (group.AnimDataOffset == 16) prm.ValueSrt2D.Translation.X = group.GetValue(Frame);
}
if (prm.Type == ShaderParamType.TexSrt)
{
if (group.AnimDataOffset == 0) prm.ValueTexSrt.Mode = (TexSrtMode)(uint)group.GetValue(Frame);
if (group.AnimDataOffset == 4) prm.ValueTexSrt.Scaling.X = group.GetValue(Frame);
if (group.AnimDataOffset == 8) prm.ValueTexSrt.Scaling.Y = group.GetValue(Frame);
if (group.AnimDataOffset == 12) prm.ValueTexSrt.Rotation = group.GetValue(Frame);
if (group.AnimDataOffset == 16) prm.ValueTexSrt.Translation.X = group.GetValue(Frame);
if (group.AnimDataOffset == 20) prm.ValueTexSrt.Translation.Y = group.GetValue(Frame);
}
if (prm.Type == ShaderParamType.TexSrtEx)
{
if (group.AnimDataOffset == 0) prm.ValueTexSrtEx.Mode = (TexSrtMode)(uint)group.GetValue(Frame);
if (group.AnimDataOffset == 4) prm.ValueTexSrtEx.Scaling.X = group.GetValue(Frame);
if (group.AnimDataOffset == 8) prm.ValueTexSrtEx.Scaling.Y = group.GetValue(Frame);
if (group.AnimDataOffset == 12) prm.ValueTexSrtEx.Rotation = group.GetValue(Frame);
if (group.AnimDataOffset == 16) prm.ValueTexSrtEx.Translation.X = group.GetValue(Frame);
if (group.AnimDataOffset == 20) prm.ValueTexSrtEx.Translation.Y = group.GetValue(Frame);
if (group.AnimDataOffset == 24) prm.ValueTexSrtEx.MatrixPointer = (uint)group.GetValue(Frame);
}
}
}
}
}
private void SetTextureAnimation(FMAT material, Material matAnim)
{
if (matAnim.Samplers.Count == 0)
return;
//Loop through sampler list for texture anims
//These store a list of indices (step curve) to grab a texture name list
//Then we'll update the active texture
foreach (Material.Sampler samplerAnim in matAnim.Samplers)
{
foreach (MatTexture texture in material.TextureMaps)
{
if (texture.SamplerName == samplerAnim.Text)
{
texture.textureState = STGenericMatTexture.TextureState.Animated;
uint index = (uint)samplerAnim.group.GetValue(Frame);
texture.animatedTexName = Textures[(int)index];
}
}
}
}
public override string ExportFilter => FileFilters.GetFilter(typeof(FMAA));
public override void Export(string FileName)
{
MaterialAnim.Export(FileName, GetResFile());
}
public override void Replace(string FileName)
{
string ext = Utils.GetExtension(FileName);
if (ext == ".bftxp")
{
MaterialAnim.Import(FileName);
MaterialAnim.Name = Text;
LoadAnim(MaterialAnim);
}
else if (ext == ".gif" || ext == ".png" || ext == ".apng")
{
BNTX bntx = PluginRuntime.bntxContainers[0];
GifToTexturePatternAnimation anim = new GifToTexturePatternAnimation(FileName, bntx, this);
MaterialAnim.Name = Text;
LoadAnim(MaterialAnim);
}
}
}
}

View file

@ -0,0 +1,968 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Syroot.NintenTools.NSW.Bfres;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.NodeWrappers;
using Switch_Toolbox.Library.Rendering;
using Switch_Toolbox.Library.Forms;
using ResU = Syroot.NintenTools.Bfres;
using ResUGX2 = Syroot.NintenTools.Bfres.GX2;
using ResGFX = Syroot.NintenTools.NSW.Bfres.GFX;
using FirstPlugin;
using FirstPlugin.Forms;
namespace Bfres.Structs
{
public class FMDL : STGenericModel
{
public bool IsEdited { get; set; }
public List<FSHP> shapes = new List<FSHP>();
public List<FSHP> depthSortedMeshes = new List<FSHP>();
public Dictionary<string, FMAT> materials = new Dictionary<string, FMAT>();
public Model Model;
public ResU.Model ModelU;
public ResFile GetResFile()
{
//ResourceFile -> FMDL -> Model Folder -> this
return ((BFRES)Parent.Parent).resFile;
}
public ResU.ResFile GetResFileU()
{
if (Parent == null || Parent.Parent == null)
return null;
return ((BFRES)Parent.Parent).resFileU;
}
public void UpdateVertexData()
{
if (Parent != null)
GetRenderer().UpdateVertexData();
}
public BFRESRender GetRenderer()
{
return ((BFRES)Parent.Parent).BFRESRender;
}
public List<FMDL> GetModelList()
{
return GetRenderer().models;
}
public FMDL()
{
ImageKey = "model";
SelectedImageKey = "model";
Checked = true;
CanReplace = true;
CanDelete = true;
Nodes.Add(new FSHPFolder());
Nodes.Add(new FMATFolder());
Nodes.Add(new FSKL.fsklNode());
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Transform", null, TransformToolAction, Keys.Control | Keys.T));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Calculate Tangents/Bitangents", null, CalcTansBitansAllShapesAction, Keys.Control | Keys.C));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Normals", null,
new ToolStripMenuItem("Smooth", null, SmoothNormalsAction),
new ToolStripMenuItem("Recalculate", null, RecalculateNormalsAction)
));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("UVs", null,
new ToolStripMenuItem("Flip Vertical", null, FlipUvsVerticalAction),
new ToolStripMenuItem("Flip Horizontal", null, FlipUvsHorizontalAction),
new ToolStripMenuItem("Copy UV Channel", null, CopyUVChannels)
));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Colors", null,
new ToolStripMenuItem(" Set Color", null, SetVertexColorDialogAction),
new ToolStripMenuItem("Set White Color", null, SetVertexColorWhiteAction)
));
}
protected void TransformToolAction(object sender, EventArgs e) { TransformTool(); }
protected void CalcTansBitansAllShapesAction(object sender, EventArgs e) { CalcTansBitansAllShapes(); }
protected void SmoothNormalsAction(object sender, EventArgs e) { SmoothNormals(); }
protected void RecalculateNormalsAction(object sender, EventArgs e) { RecalculateNormals(); }
protected void FlipUvsVerticalAction(object sender, EventArgs e) { FlipUvsVertical(); }
protected void FlipUvsHorizontalAction(object sender, EventArgs e) { FlipUvsHorizontal(); }
protected void CopyUVChannels(object sender, EventArgs e) { CopyUVChannels(); }
protected void SetVertexColorDialogAction(object sender, EventArgs e) { SetVertexColorDialog(); }
protected void SetVertexColorWhiteAction(object sender, EventArgs e) { SetVertexColorWhite(); }
public override void Delete()
{
DialogResult dialogResult = MessageBox.Show("Are you sure you want to remove this model? This cannot be undone!", "", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
shapes.Clear();
materials.Clear();
UpdateVertexData();
Nodes.Clear();
((BFRESGroupNode)Parent).RemoveChild(this);
}
}
public void CopyUVChannels()
{
CopyUVChannelDialog dialog = new CopyUVChannelDialog();
dialog.LoadUVAttributes();
if (dialog.ShowDialog() == DialogResult.OK)
{
int dest = dialog.DestIndex;
int source = dialog.SourceIndex;
bool CanCreateUV = false;
bool HasDestUV = false;
bool ShownDialog = false;
foreach (var shape in shapes)
{
//If no source, there's nothing to copy from
if (!shape.vertexAttributes.Any(x => x.Name == $"_u{source}"))
continue;
if ((!shape.vertexAttributes.Any(x => x.Name == $"_u{dest}")))
{
//Only show the dialog once for creating UV channels
if (!CanCreateUV && !ShownDialog)
{
DialogResult dialogResult = MessageBox.Show($"Some of the objects are missing the destenation uv channel ({dest}) to copy to. Create one?", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dialogResult == DialogResult.Yes)
{
CanCreateUV = true;
ShownDialog = true;
}
}
if (CanCreateUV)
{
FSHP.VertexAttribute att = new FSHP.VertexAttribute();
att.Name = $"_u{dest}";
att.Format = ResGFX.AttribFormat.Format_16_16_Single;
shape.vertexAttributes.Add(att);
HasDestUV = true;
}
}
else
HasDestUV = true;
if (HasDestUV)
{
Cursor.Current = Cursors.WaitCursor;
shape.CopyUVChannel(dialog.SourceIndex, dialog.DestIndex);
shape.SaveVertexBuffer();
UpdateVertexData();
Cursor.Current = Cursors.Default;
}
shape.CopyUVChannel(dialog.SourceIndex, dialog.DestIndex);
shape.SaveVertexBuffer();
}
}
UpdateVertexData();
}
public void FlipUvsVertical()
{
foreach (var shape in shapes)
{
if (!shape.HasUV0())
{
MessageBox.Show($"Error! {Text} does not have UVs!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
shape.FlipUvsVertical();
shape.SaveVertexBuffer();
}
UpdateVertexData();
}
public void FlipUvsHorizontal()
{
foreach (var shape in shapes)
{
if (!shape.HasUV0())
{
MessageBox.Show($"Error! {Text} does not have UVs!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
shape.FlipUvsHorizontal();
shape.SaveVertexBuffer();
}
UpdateVertexData();
}
private void BatchAttributeEdit()
{
AttributeEditor editor = new AttributeEditor();
editor.LoadObjects(this);
if (editor.ShowDialog() == DialogResult.OK)
{
}
}
private void SetVertexColorDialog()
{
ColorDialog dlg = new ColorDialog();
if (dlg.ShowDialog() == DialogResult.OK)
{
foreach (FSHP shp in shapes)
{
shp.CheckVertexColors();
shp.SetVertexColor(new OpenTK.Vector4(
dlg.Color.R / 255.0f,
dlg.Color.G / 255.0f,
dlg.Color.B / 255.0f,
dlg.Color.A / 255.0f));
shp.SaveVertexBuffer();
}
}
UpdateVertexData();
}
private void SetVertexColorWhite()
{
foreach (FSHP shp in shapes)
{
shp.CheckVertexColors();
shp.SetVertexColor(new OpenTK.Vector4(1, 1, 1, 1));
shp.SaveVertexBuffer();
}
UpdateVertexData();
}
private void SmoothNormals()
{
Cursor.Current = Cursors.WaitCursor;
foreach (FSHP shp in shapes)
{
bool HasNormals = shp.vertexAttributes.Any(x => x.Name == "_n0");
if (HasNormals)
shp.SmoothNormals();
shp.SaveVertexBuffer();
}
UpdateVertexData();
Cursor.Current = Cursors.Default;
}
private void RecalculateNormals()
{
Cursor.Current = Cursors.WaitCursor;
foreach (FSHP shp in shapes)
{
bool HasNormals = shp.vertexAttributes.Any(x => x.Name == "_n0");
if (HasNormals)
shp.CalculateNormals();
shp.SaveVertexBuffer();
}
UpdateVertexData();
Cursor.Current = Cursors.Default;
}
public override void Rename()
{
RenameDialog dialog = new RenameDialog();
dialog.SetString(Text);
if (dialog.ShowDialog() == DialogResult.OK)
{
Text = dialog.textBox1.Text;
}
}
private void CalcTansBitansAllShapes()
{
Cursor.Current = Cursors.WaitCursor;
foreach (FSHP shp in shapes)
{
bool HasTans = shp.vertexAttributes.Any(x => x.Name == "_t0");
bool HasBiTans = shp.vertexAttributes.Any(x => x.Name == "_b0");
if (!shp.HasUV0())
{
MessageBox.Show($"Error! {Text} does not have UVs!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (!HasBiTans)
{
DialogResult dialogResult2 = MessageBox.Show("Mesh does not have bitangents. Do you want to create them? (will make file size bigger)", "", MessageBoxButtons.YesNo);
FSHP.VertexAttribute att2 = new FSHP.VertexAttribute();
att2.Name = "_b0";
att2.Format = ResGFX.AttribFormat.Format_10_10_10_2_SNorm;
if (dialogResult2 == DialogResult.Yes)
{
if (!HasBiTans)
shp.vertexAttributes.Add(att2);
}
}
if (!HasTans)
{
DialogResult dialogResult = MessageBox.Show("Mesh does not have tangets. Do you want to create them? (will make file size bigger)", "", MessageBoxButtons.YesNo);
FSHP.VertexAttribute att = new FSHP.VertexAttribute();
att.Name = "_t0";
att.Format = ResGFX.AttribFormat.Format_10_10_10_2_SNorm;
if (dialogResult == DialogResult.Yes)
{
if (!HasTans)
shp.vertexAttributes.Add(att);
}
}
bool UseUVLayer2 = false;
//for BOTW if it uses UV layer 2 for normal maps use second UV map
if (shp.GetMaterial().shaderassign.options.ContainsKey("uking_texture2_texcoord")) {
float value = float.Parse(shp.GetMaterial().shaderassign.options["uking_texture2_texcoord"]);
if (value == 1)
UseUVLayer2 = true;
}
shp.CalculateTangentBitangent(UseUVLayer2);
shp.SaveVertexBuffer();
}
UpdateVertexData();
Cursor.Current = Cursors.Default;
}
public void CopyMaterial(FMAT selectedMaterial)
{
CopyMaterialMenu menu = new CopyMaterialMenu();
menu.LoadMaterials(selectedMaterial.Text, GetModelList());
if (menu.ShowDialog() == DialogResult.OK)
{
foreach (TreeNode mdl in menu.materialTreeView.Nodes)
{
foreach (TreeNode n in mdl.Nodes)
{
if (n.Checked)
{
if (materials.ContainsKey(n.Text))
SetCopiedMaterialData(menu, selectedMaterial, materials[n.Text]);
}
}
}
LibraryGUI.Instance.UpdateViewport();
}
}
private void SetCopiedMaterialData(CopyMaterialMenu menu,
FMAT selectedMaterial, FMAT targetMaterial)
{
targetMaterial.Material.Flags = selectedMaterial.Material.Flags;
targetMaterial.Material.UserDatas = selectedMaterial.Material.UserDatas;
targetMaterial.Material.UserDataDict = selectedMaterial.Material.UserDataDict;
if (menu.chkBoxRenderInfo.Checked)
{
targetMaterial.Material.RenderInfoDict = selectedMaterial.Material.RenderInfoDict;
targetMaterial.Material.RenderInfos = selectedMaterial.Material.RenderInfos;
}
if (menu.chkBoxShaderOptions.Checked)
{
targetMaterial.Material.ShaderAssign = selectedMaterial.Material.ShaderAssign;
}
if (menu.chkBoxShaderParams.Checked)
{
targetMaterial.Material.ShaderParamData = selectedMaterial.Material.ShaderParamData;
targetMaterial.Material.ShaderParamDict = selectedMaterial.Material.ShaderParamDict;
targetMaterial.Material.ShaderParams = selectedMaterial.Material.ShaderParams;
targetMaterial.Material.VolatileFlags = selectedMaterial.Material.VolatileFlags;
}
if (menu.chkBoxTextures.Checked)
{
targetMaterial.Material.SamplerDict = selectedMaterial.Material.SamplerDict;
targetMaterial.Material.Samplers = selectedMaterial.Material.Samplers;
targetMaterial.Material.SamplerSlotArray = selectedMaterial.Material.SamplerSlotArray;
targetMaterial.Material.TextureSlotArray = selectedMaterial.Material.TextureSlotArray;
targetMaterial.Material.TextureRefs = selectedMaterial.Material.TextureRefs;
}
targetMaterial.ReadMaterial(targetMaterial.Material);
}
private void TransformTool()
{
TransformMeshTool transform = new TransformMeshTool();
foreach (var mesh in shapes)
{
transform.LoadGenericMesh(mesh, UpdateVertexData);
}
transform.CacheList();
if (transform.ShowDialog() != DialogResult.OK)
{
int curShp = 0;
foreach (var mesh in shapes)
{
mesh.vertices = transform.cachedBackups[curShp].vertices;
curShp++;
}
UpdateVertexData();
}
}
public override string ExportFilter => FileFilters.GetFilter(typeof(FMDL));
public override void Export(string FileName)
{
string ext = System.IO.Path.GetExtension(FileName);
ext = ext.ToLower();
switch (ext)
{
case ".bfmdl":
if (GetResFileU() != null)
ModelU.Export(FileName, GetResFileU());
else
Model.Export(FileName, GetResFile());
break;
default:
List<STGenericTexture> textures = new List<STGenericTexture>();
foreach (var mat in materials)
{
foreach (var texref in mat.Value.TextureMaps)
{
foreach (var bntx in PluginRuntime.bntxContainers)
{
if (bntx.Textures.ContainsKey(texref.Name))
textures.Add(bntx.Textures[texref.Name]);
}
}
}
AssimpData assimp = new AssimpData();
assimp.SaveFromModel(this, FileName, textures, Skeleton, Skeleton.Node_Array.ToList());
break;
}
}
public override void Replace(string FileName) {
AddOjects(FileName, GetResFile(), GetResFileU());
}
public void Replace(string FileName, ResFile resFileNX, ResU.ResFile resFileU) {
AddOjects(FileName, resFileNX, resFileU);
}
//Function addes shapes, vertices and meshes
public void AddOjects(string FileName, ResFile resFileNX, ResU.ResFile resFileU, bool Replace = true)
{
int totalSkinCountLimiter = 0;
bool IsWiiU = (resFileU != null);
if (shapes.Count > 0)
totalSkinCountLimiter = shapes[0].VertexSkinCount;
int MatStartIndex = materials.Count;
string ext = System.IO.Path.GetExtension(FileName);
ext = ext.ToLower();
switch (ext)
{
case ".bfobj":
Cursor.Current = Cursors.WaitCursor;
if (Replace)
{
shapes.Clear();
Nodes["FshpFolder"].Nodes.Clear();
}
if (IsWiiU)
{
var shpS = new ResU.Shape();
var vertexBufferU = new ResU.VertexBuffer();
shpS.Import(FileName, vertexBufferU, resFileU);
FSHP shapeS = new FSHP();
shapeS.ShapeU = shpS;
BfresWiiU.ReadShapesVertices(shapeS, shpS, vertexBufferU, this);
shapes.Add(shapeS);
Nodes["FshpFolder"].Nodes.Add(shapeS);
}
else
{
Shape shpS = new Shape();
VertexBuffer vertexBuffer = new VertexBuffer();
shpS.Import(FileName, vertexBuffer);
FSHP shapeS = new FSHP();
shapeS.Shape = shpS;
BfresSwitch.ReadShapesVertices(shapeS, shpS, vertexBuffer, this);
shapes.Add(shapeS);
Nodes["FshpFolder"].Nodes.Add(shapeS);
}
IsEdited = true;
Cursor.Current = Cursors.Default;
break;
case ".bfmdl":
Cursor.Current = Cursors.WaitCursor;
if (Replace)
{
shapes.Clear();
Nodes["FshpFolder"].Nodes.Clear();
materials.Clear();
Nodes["FmatFolder"].Nodes.Clear();
}
if (IsWiiU)
{
var mdlU = new ResU.Model();
mdlU.Import(FileName, resFileU);
mdlU.Name = Text;
BfresWiiU.ReadModel(this, mdlU);
}
else
{
Model mdl = new Model();
mdl.Import(FileName, resFileNX);
mdl.Name = Text;
BfresSwitch.ReadModel(this, mdl);
}
UpdateVertexData();
IsEdited = true;
Cursor.Current = Cursors.Default;
break;
case ".csv":
CsvModel csvModel = new CsvModel();
csvModel.LoadFile(new System.IO.FileStream(FileName, System.IO.FileMode.Open), true);
if (csvModel.objects.Count == 0)
{
MessageBox.Show("No models found!");
return;
}
BfresModelImportSettings csvsettings = new BfresModelImportSettings();
csvsettings.DisableMaterialEdits();
csvsettings.SkinCountLimit = totalSkinCountLimiter;
csvsettings.SetModelAttributes(csvModel.objects[0]);
if (csvsettings.ShowDialog() == DialogResult.OK)
{
if (Replace)
{
shapes.Clear();
Nodes["FshpFolder"].Nodes.Clear();
}
Cursor.Current = Cursors.WaitCursor;
foreach (STGenericObject obj in csvModel.objects)
{
FSHP shape = new FSHP();
shape.VertexBufferIndex = shapes.Count;
shape.vertices = obj.vertices;
shape.MaterialIndex = 0;
shape.vertexAttributes = csvsettings.CreateNewAttributes();
shape.BoneIndex = 0;
shape.Text = obj.ObjectName;
shape.lodMeshes = obj.lodMeshes;
shape.CreateNewBoundingBoxes();
shape.CreateBoneList(obj, this);
shape.CreateIndexList(obj, this);
//Todo find better way. Currently uses import settings now
shape.ApplyImportSettings(csvsettings, GetMaterial(shape.MaterialIndex));
shape.VertexSkinCount = obj.GetMaxSkinInfluenceCount();
shape.SaveShape(IsWiiU);
shape.SaveVertexBuffer();
shape.BoneIndices = new List<ushort>();
if (IsWiiU)
{
shape.ShapeU.SubMeshBoundingIndices = new List<ushort>();
shape.ShapeU.SubMeshBoundingIndices.Add(0);
shape.ShapeU.SubMeshBoundingNodes = new List<ResU.BoundingNode>();
shape.ShapeU.SubMeshBoundingNodes.Add(new ResU.BoundingNode()
{
LeftChildIndex = 0,
NextSibling = 0,
SubMeshIndex = 0,
RightChildIndex = 0,
Unknown = 0,
SubMeshCount = 1,
});
}
Nodes["FshpFolder"].Nodes.Add(shape);
shapes.Add(shape);
}
Cursor.Current = Cursors.Default;
}
IsEdited = true;
break;
default:
AssimpData assimp = new AssimpData();
assimp.LoadFile(FileName);
if (assimp.objects.Count == 0)
{
MessageBox.Show("No models found!");
return;
}
BfresModelImportSettings settings = new BfresModelImportSettings();
settings.SetModelAttributes(assimp.objects[0]);
if (settings.ShowDialog() == DialogResult.OK)
{
bool UseMats = settings.ExternalMaterialPath != string.Empty;
if (Replace)
{
shapes.Clear();
Nodes["FshpFolder"].Nodes.Clear();
}
Cursor.Current = Cursors.WaitCursor;
if (Replace && UseMats)
{
materials.Clear();
Nodes["FmatFolder"].Nodes.Clear();
MatStartIndex = 0;
}
if (UseMats)
{
foreach (STGenericMaterial mat in assimp.materials)
{
FMAT fmat = new FMAT();
materials.Add(fmat.Text, fmat);
Nodes["FmatFolder"].Nodes.Add(fmat);
if (resFileU != null)
{
fmat.MaterialU = new ResU.Material();
fmat.MaterialU.Import(settings.ExternalMaterialPath, resFileU);
BfresWiiU.ReadMaterial(fmat, fmat.MaterialU);
}
else
{
fmat.Material = new Material();
fmat.Material.Import(settings.ExternalMaterialPath);
fmat.ReadMaterial(fmat.Material);
}
fmat.Text = mat.Text;
//Setup placeholder textures
//Note we can't add/remove samplers so we must fill these slots
foreach (var t in fmat.TextureMaps)
{
t.wrapModeS = 0;
t.wrapModeT = 0;
switch (t.Type)
{
case STGenericMatTexture.TextureType.Diffuse:
t.Name = "Basic_Alb";
break;
case STGenericMatTexture.TextureType.Emission:
t.Name = "Basic_Emm";
break;
case STGenericMatTexture.TextureType.Normal:
t.Name = "Basic_Nrm";
break;
case STGenericMatTexture.TextureType.Specular:
t.Name = "Basic_Spm";
break;
case STGenericMatTexture.TextureType.SphereMap:
t.Name = "Basic_Sphere";
break;
case STGenericMatTexture.TextureType.Metalness:
t.Name = "Basic_Mtl";
break;
case STGenericMatTexture.TextureType.Roughness:
t.Name = "Basic_Rgh";
break;
case STGenericMatTexture.TextureType.MRA:
t.Name = "Basic_MRA";
break;
case STGenericMatTexture.TextureType.Shadow:
t.Name = "Basic_Bake_st0";
break;
case STGenericMatTexture.TextureType.Light:
t.Name = "Basic_Bake_st1";
break;
}
}
if (PluginRuntime.bntxContainers.Count > 0 && Parent != null)
{
foreach (var node in Parent.Parent.Nodes)
{
if (node is BNTX)
{
var bntx = (BNTX)node;
bntx.ImportBasicTextures("Basic_Alb");
bntx.ImportBasicTextures("Basic_Nrm");
bntx.ImportBasicTextures("Basic_Spm");
bntx.ImportBasicTextures("Basic_Sphere");
bntx.ImportBasicTextures("Basic_Mtl");
bntx.ImportBasicTextures("Basic_Rgh");
bntx.ImportBasicTextures("Basic_MRA");
bntx.ImportBasicTextures("Basic_Bake_st0");
bntx.ImportBasicTextures("Basic_Bake_st1");
bntx.ImportBasicTextures("Basic_Emm");
}
}
}
if (PluginRuntime.ftexContainers.Count > 0)
{
foreach (var node in Parent.Parent.Nodes)
{
if (node is BFRESGroupNode)
{
if (((BFRESGroupNode)node).Type == BRESGroupType.Textures)
{
var ftexCont = (BFRESGroupNode)node;
ftexCont.ImportBasicTextures("Basic_Alb");
ftexCont.ImportBasicTextures("Basic_Nrm");
ftexCont.ImportBasicTextures("Basic_Spm");
ftexCont.ImportBasicTextures("Basic_Sphere");
ftexCont.ImportBasicTextures("Basic_Mtl");
ftexCont.ImportBasicTextures("Basic_Rgh");
ftexCont.ImportBasicTextures("Basic_MRA");
ftexCont.ImportBasicTextures("Basic_Bake_st0");
ftexCont.ImportBasicTextures("Basic_Bake_st1");
ftexCont.ImportBasicTextures("Basic_Emm");
}
}
}
}
foreach (var tex in mat.TextureMaps)
{
foreach (var t in fmat.TextureMaps)
{
if (t.Type == tex.Type)
{
t.Name = tex.Name;
t.wrapModeS = tex.wrapModeS;
t.wrapModeT = tex.wrapModeT;
t.wrapModeW = tex.wrapModeW;
t.Type = tex.Type;
}
}
}
List<string> keyList = new List<string>(materials.Keys);
fmat.Text = Utils.RenameDuplicateString(keyList, fmat.Text);
if (resFileU != null)
{
fmat.MaterialU.Name = Text;
fmat.SetMaterial(fmat.MaterialU);
}
else
{
fmat.Material.Name = Text;
fmat.SetMaterial(fmat.Material);
}
}
}
if (settings.ImportBones)
{
if (assimp.skeleton.bones.Count > 0)
{
Skeleton.bones.Clear();
foreach (var bone in assimp.skeleton.bones)
{
Skeleton.bones.Add(bone);
}
if (IsWiiU)
BfresWiiU.SaveSkeleton(Skeleton);
else
BfresSwitch.SaveSkeleton(Skeleton);
}
}
if (materials.Count <= 0)
{
//Force material creation if there is none present
FMAT fmat = new FMAT();
fmat.Text = "NewMaterial";
materials.Add(fmat.Text, fmat);
Nodes["FmatFolder"].Nodes.Add(fmat);
if (resFileU != null)
{
fmat.MaterialU = new ResU.Material();
fmat.MaterialU.Name = "NewMaterial";
BfresWiiU.ReadMaterial(fmat, fmat.MaterialU);
}
else
{
fmat.Material = new Material();
fmat.Material.Name = "NewMaterial";
fmat.ReadMaterial(fmat.Material);
}
}
foreach (STGenericObject obj in assimp.objects)
{
FSHP shape = new FSHP();
Nodes["FshpFolder"].Nodes.Add(shape);
shapes.Add(shape);
shape.VertexBufferIndex = shapes.Count;
shape.vertices = obj.vertices;
shape.vertexAttributes = settings.CreateNewAttributes();
shape.BoneIndex = obj.BoneIndex;
if (UseMats)
shape.MaterialIndex = obj.MaterialIndex + MatStartIndex;
else
shape.MaterialIndex = 0;
if (materials.Count >= shape.MaterialIndex)
shape.MaterialIndex = 0;
shape.Text = obj.ObjectName;
shape.lodMeshes = obj.lodMeshes;
shape.CreateNewBoundingBoxes();
shape.CreateBoneList(obj, this);
shape.CreateIndexList(obj, this);
shape.ApplyImportSettings(settings, GetMaterial(shape.MaterialIndex));
shape.VertexSkinCount = obj.GetMaxSkinInfluenceCount();
shape.SaveShape(IsWiiU);
shape.SaveVertexBuffer();
shape.BoneIndices = new List<ushort>();
if (IsWiiU)
{
shape.ShapeU.SubMeshBoundingIndices = new List<ushort>();
shape.ShapeU.SubMeshBoundingIndices.Add(0);
shape.ShapeU.SubMeshBoundingNodes = new List<ResU.BoundingNode>();
shape.ShapeU.SubMeshBoundingNodes.Add(new ResU.BoundingNode()
{
LeftChildIndex = 0,
NextSibling = 0,
SubMeshIndex = 0,
RightChildIndex = 0,
Unknown = 0,
SubMeshCount = 1,
});
}
List<string> keyList = shapes.Select(o => o.Text).ToList();
shape.Text = Utils.RenameDuplicateString(keyList, shape.Text);
}
IsEdited = true;
Cursor.Current = Cursors.Default;
}
break;
}
if (IsEdited)
UpdateVertexData();
}
public FMAT GetMaterial(int index)
{
return materials.Values.ElementAt(index);
}
public void AddMaterials(string FileName, bool Replace = true)
{
string ext = System.IO.Path.GetExtension(FileName);
ext = ext.ToLower();
switch (ext)
{
case ".bfmat":
Cursor.Current = Cursors.WaitCursor;
if (Replace)
{
materials.Clear();
Nodes["FmatFolder"].Nodes.Clear();
}
FMAT mat = new FMAT();
mat.Material = new Material();
mat.Material.Import(FileName);
mat.ReadMaterial(mat.Material);
List<string> keyList = new List<string>(this.materials.Keys);
mat.Material.Name = Utils.RenameDuplicateString(keyList, mat.Material.Name);
keyList.Clear();
Text = mat.Material.Name;
materials.Add(mat.Text, mat);
Nodes["FmatFolder"].Nodes.Add(mat);
break;
}
}
public override void OnClick(TreeView treeView)
{
UpdateEditor();
}
public void UpdateEditor(){
((BFRES)Parent.Parent).LoadEditors(this);
}
private void CreateSkeleton()
{
}
private void CreateBones(STBone bone)
{
Bone bn = new Bone();
bn.BillboardIndex = (ushort)bone.BillboardIndex;
bn.Flags = BoneFlags.Visible;
bn.FlagsRotation = BoneFlagsRotation.EulerXYZ;
bn.FlagsTransform = BoneFlagsTransform.None;
bn.FlagsTransformCumulative = BoneFlagsTransformCumulative.None;
bn.Name = bone.Text;
bn.RigidMatrixIndex = 0;
bn.Rotation = new Syroot.Maths.Vector4F(bone.rotation[0],
bone.rotation[1], bone.rotation[2], bone.rotation[3]);
bn.Position = new Syroot.Maths.Vector3F(bone.position[0],
bone.position[1], bone.position[2]);
bn.Scale = new Syroot.Maths.Vector3F(bone.scale[0],
bone.scale[1], bone.scale[2]);
bn.UserData = new List<UserData>();
bn.UserDataDict = new ResDict();
}
public FSKL Skeleton
{
get
{
return skeleton;
}
set
{
skeleton = value;
}
}
private FSKL skeleton = new FSKL();
}
}

View file

@ -0,0 +1,545 @@
using System;
using System.Collections.Generic;
using System.IO;
using Syroot.NintenTools.NSW.Bfres;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library.Rendering;
using Switch_Toolbox.Library.Forms;
using ResU = Syroot.NintenTools.Bfres;
using ResUGX2 = Syroot.NintenTools.Bfres.GX2;
using ResGFX = Syroot.NintenTools.NSW.Bfres.GFX;
using FirstPlugin;
using OpenTK;
using FirstPlugin.Forms;
namespace Bfres.Structs
{
public class FMATFolder : TreeNodeCustom
{
public FMATFolder()
{
Text = "Materials";
Name = "FmatFolder";
ContextMenuStrip = new STContextMenuStrip();
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Import Material", null, Import, Keys.Control | Keys.I));
ContextMenuStrip.Items.Add(new ToolStripSeparator());
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Export All Materials", null, ExportAll, Keys.Control | Keys.A));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Replace (From Folder)",null, ReplaceBatch, Keys.Control | Keys.R));
}
public void ExportAll(object sender, EventArgs args)
{
FolderSelectDialog sfd = new FolderSelectDialog();
if (sfd.ShowDialog() == DialogResult.OK)
{
string folderPath = sfd.SelectedPath;
foreach (FMAT mat in Nodes)
{
mat.Export(folderPath + '\\' + mat.Text + ".bfmat");
}
}
}
public void ReplaceBatch(object sender, EventArgs args)
{
FolderSelectDialog ofd = new FolderSelectDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
string folderPath = ofd.SelectedPath;
foreach (var file in Directory.GetFiles(folderPath))
{
string Name = Path.GetFileNameWithoutExtension(file);
if (((FMDL)Parent).materials.ContainsKey(Name) &&
(file.EndsWith(".bfmat")))
{
((FMDL)Parent).materials[Name].Replace(file);
}
}
}
LibraryGUI.Instance.UpdateViewport();
}
public void Import(object sender, EventArgs args)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Bfres Material |*.bfmat;";
ofd.Multiselect = true;
if (ofd.ShowDialog() == DialogResult.OK)
{
foreach (string file in ofd.FileNames)
((FMDL)Parent).AddMaterials(file, false);
}
}
public override void OnClick(TreeView treeView)
{
}
}
public class FMAT : STGenericMaterial
{
public FMAT()
{
Checked = true;
ImageKey = "material";
SelectedImageKey = "material";
ContextMenuStrip = new STContextMenuStrip();
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Export", null, Export, Keys.Control | Keys.E));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Replace", null, Replace, Keys.Control | Keys.R));
ContextMenuStrip.Items.Add(new ToolStripSeparator());
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Copy", null, Copy, Keys.Control | Keys.C));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Rename", null, Rename, Keys.Control | Keys.N));
}
public ResFile GetResFile()
{
return ((FMDL)Parent.Parent).GetResFile();
}
public ResU.ResFile GetResFileU()
{
return ((FMDL)Parent.Parent).GetResFileU();
}
public bool Enabled = true;
public bool isTransparent = false;
public override void OnClick(TreeView treeView)
{
UpdateEditor();
}
public void UpdateEditor()
{
((BFRES)Parent.Parent.Parent.Parent).LoadEditors(this);
}
public void UpdateTextureMaps()
{
((BFRES)Parent.Parent.Parent.Parent).BFRESRender.UpdateSingleMaterialTextureMaps(this);
}
public BFRESRender GetRenderer()
{
return ((BFRES)Parent.Parent.Parent.Parent).BFRESRender;
}
public void SetActiveGame()
{
Runtime.activeGame = Runtime.ActiveGame.KSA;
string ShaderName = shaderassign.ShaderArchive;
string ShaderModel = shaderassign.ShaderModel;
if (ShaderName == null || ShaderModel == null)
return;
if (ShaderName == "alRenderMaterial" || ShaderName == "alRenderCloudLayer" || ShaderName == "alRenderSky")
Runtime.activeGame = Runtime.ActiveGame.SMO;
else if (ShaderName == "Turbo_UBER")
Runtime.activeGame = Runtime.ActiveGame.MK8D;
else if (ShaderName.Contains("uking_mat"))
Runtime.activeGame = Runtime.ActiveGame.BOTW;
else if (ShaderName.Contains("Blitz_UBER"))
Runtime.activeGame = Runtime.ActiveGame.Splatoon2;
else
Runtime.activeGame = Runtime.ActiveGame.KSA;
}
private void Rename(object sender, EventArgs args)
{
RenameDialog dialog = new RenameDialog();
dialog.SetString(Text);
if (dialog.ShowDialog() == DialogResult.OK)
{
((FMDL)Parent.Parent).materials.Remove(Text);
Text = dialog.textBox1.Text;
((FMDL)Parent.Parent).materials.Add(Text, this);
}
}
private void Copy(object sender, EventArgs args)
{
((FMDL)Parent.Parent).CopyMaterial(this);
}
private void Export(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Supported Formats|*.bfmat;";
sfd.DefaultExt = ".bfmat";
sfd.FileName = Text;
if (sfd.ShowDialog() == DialogResult.OK)
{
Export(sfd.FileName);
}
}
public void Export(string path)
{
if (GetResFileU() != null)
MaterialU.Export(path, GetResFileU());
else
Material.Export(path, GetResFile());
}
private void Replace(object sender, EventArgs args)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Supported Formats|*.bfmat;";
if (ofd.ShowDialog() == DialogResult.OK)
{
Replace(ofd.FileName);
}
}
public void Replace(string path)
{
if (GetResFileU() != null)
{
MaterialU.Import(path, GetResFileU());
MaterialU.Name = Text;
BfresWiiU.ReadMaterial(this, MaterialU);
}
else
{
Material.Import(path);
Material.Name = Text;
BfresSwitch.ReadMaterial(this, Material);
}
}
public Dictionary<string, float[]> anims = new Dictionary<string, float[]>();
public List<BfresRenderInfo> renderinfo = new List<BfresRenderInfo>();
public Dictionary<string, BfresShaderParam> matparam = new Dictionary<string, BfresShaderParam>();
public Dictionary<string, BfresShaderParam> animatedMatParams = new Dictionary<string, BfresShaderParam>();
public Material Material;
public ResU.Material MaterialU;
public ShaderAssign shaderassign = new ShaderAssign();
public class ShaderAssign
{
public string ShaderModel = "";
public string ShaderArchive = "";
public Dictionary<string, string> options = new Dictionary<string, string>();
public Dictionary<string, string> samplers = new Dictionary<string, string>();
public Dictionary<string, string> attributes = new Dictionary<string, string>();
}
public bool HasDiffuseMap = false;
public bool HasNormalMap = false;
public bool HasSpecularMap = false;
public bool HasEmissionMap = false;
public bool HasDiffuseLayer = false;
public bool HasTeamColorMap = false; //Splatoon uses this (TLC)
public bool HasTransparencyMap = false;
public bool HasShadowMap = false;
public bool HasAmbientOcclusionMap = false;
public bool HasLightMap = false;
public bool HasSphereMap = false;
public bool HasSubSurfaceScatteringMap = false;
//PBR (Switch) data
public bool HasMetalnessMap = false;
public bool HasRoughnessMap = false;
public bool HasMRA = false;
}
public class BfresShaderParam
{
public ShaderParamType Type;
public string Name;
public bool HasPadding;
public int PaddingLength = 0;
public float[] ValueFloat;
public bool[] ValueBool;
public uint[] ValueUint;
public int[] ValueInt;
public byte[] ValueReserved;
public Srt2D ValueSrt2D;
public Srt3D ValueSrt3D;
public TexSrt ValueTexSrt;
public TexSrtEx ValueTexSrtEx;
//If a data set is not defined then defaults in this to save back properly
//Note this may be rarely needed or not at all
public byte[] Value_Unk;
private void ReadSRT2D(FileReader reader)
{
ValueSrt2D = new Srt2D();
ValueSrt2D.Scaling = reader.ReadVec2SY();
ValueSrt2D.Rotation = reader.ReadSingle();
ValueSrt2D.Translation = reader.ReadVec2SY();
}
private void ReadSRT3D(FileReader reader)
{
ValueSrt3D = new Srt3D();
ValueSrt3D.Scaling = reader.ReadVec3SY();
ValueSrt3D.Rotation = reader.ReadVec3SY();
ValueSrt3D.Translation = reader.ReadVec3SY();
}
private void ReadTexSrt(FileReader reader)
{
ValueTexSrt = new TexSrt();
ValueTexSrt.Mode = reader.ReadEnum<TexSrtMode>(false);
ValueTexSrt.Scaling = reader.ReadVec2SY();
ValueTexSrt.Rotation = reader.ReadSingle();
ValueTexSrt.Translation = reader.ReadVec2SY();
}
private void ReadTexSrtEx(FileReader reader)
{
ValueTexSrtEx = new TexSrtEx();
ValueTexSrtEx.Mode = reader.ReadEnum<TexSrtMode>(true);
ValueTexSrtEx.Scaling = reader.ReadVec2SY();
ValueTexSrtEx.Rotation = reader.ReadSingle();
ValueTexSrtEx.Translation = reader.ReadVec2SY();
ValueTexSrtEx.MatrixPointer = reader.ReadUInt32();
}
public ShaderParamType GetTypeWiiU(ResU.ShaderParamType type)
{
return (ShaderParamType)System.Enum.Parse(typeof(ShaderParamType), type.ToString());
}
public ResU.ShaderParamType SetTypeWiiU(ShaderParamType type)
{
return (ResU.ShaderParamType)System.Enum.Parse(typeof(ResU.ShaderParamType), type.ToString());
}
public void ReadValue(FileReader reader, int Size)
{
switch (Type)
{
case ShaderParamType.Bool:
case ShaderParamType.Bool2:
case ShaderParamType.Bool3:
case ShaderParamType.Bool4:
ValueBool = reader.ReadBooleans(Size / sizeof(bool)); break;
case ShaderParamType.Float:
case ShaderParamType.Float2:
case ShaderParamType.Float3:
case ShaderParamType.Float4:
case ShaderParamType.Float2x2:
case ShaderParamType.Float2x3:
case ShaderParamType.Float2x4:
case ShaderParamType.Float4x2:
case ShaderParamType.Float4x3:
case ShaderParamType.Float4x4:
ValueFloat = reader.ReadSingles(Size / sizeof(float)); break;
case ShaderParamType.Int:
case ShaderParamType.Int2:
case ShaderParamType.Int3:
case ShaderParamType.Int4:
ValueInt = reader.ReadInt32s(Size / sizeof(int)); break;
case ShaderParamType.Reserved2:
case ShaderParamType.Reserved3:
case ShaderParamType.Reserved4:
ValueReserved = reader.ReadBytes(Size / sizeof(byte)); break;
case ShaderParamType.Srt2D:
ReadSRT2D(reader); break;
case ShaderParamType.Srt3D:
ReadSRT3D(reader); break;
case ShaderParamType.TexSrt:
ReadTexSrt(reader); break;
case ShaderParamType.TexSrtEx:
ReadTexSrtEx(reader); break;
case ShaderParamType.UInt:
case ShaderParamType.UInt2:
case ShaderParamType.UInt3:
case ShaderParamType.UInt4:
ValueUint = reader.ReadUInt32s(Size / sizeof(uint)); break;
// Invalid
default:
throw new ArgumentException($"Invalid {nameof(ShaderParamType)} {Type}.",
nameof(Type));
}
}
public void WriteValue(FileWriter writer)
{
switch (Type)
{
case ShaderParamType.Bool:
case ShaderParamType.Bool2:
case ShaderParamType.Bool3:
case ShaderParamType.Bool4:
writer.Write(ValueBool); break;
case ShaderParamType.Float:
case ShaderParamType.Float2:
case ShaderParamType.Float3:
case ShaderParamType.Float4:
case ShaderParamType.Float2x2:
case ShaderParamType.Float2x3:
case ShaderParamType.Float2x4:
case ShaderParamType.Float4x2:
case ShaderParamType.Float4x3:
case ShaderParamType.Float4x4:
writer.Write(ValueFloat); break;
case ShaderParamType.Int:
case ShaderParamType.Int2:
case ShaderParamType.Int3:
case ShaderParamType.Int4:
writer.Write(ValueInt); break;
case ShaderParamType.Reserved2:
case ShaderParamType.Reserved3:
case ShaderParamType.Reserved4:
writer.Write(ValueInt); break;
case ShaderParamType.Srt2D:
WriteSRT2D(writer); break;
case ShaderParamType.Srt3D:
WriteSRT3D(writer); break;
case ShaderParamType.TexSrt:
WriteTexSrt(writer); break;
case ShaderParamType.TexSrtEx:
WriteTexSrtEx(writer); break;
case ShaderParamType.UInt:
case ShaderParamType.UInt2:
case ShaderParamType.UInt3:
case ShaderParamType.UInt4:
writer.Write(ValueUint); break;
// Invalid
default:
throw new ArgumentException($"Invalid {nameof(ShaderParamType)} {Type}.",
nameof(Type));
}
Console.WriteLine("PaddingLength " + PaddingLength);
if (PaddingLength > 0)
writer.Write(new byte[PaddingLength]);
}
private void WriteSRT2D(FileWriter writer)
{
writer.Write(ValueSrt2D.Scaling);
writer.Write(ValueSrt2D.Rotation);
writer.Write(ValueSrt2D.Translation);
}
private void WriteSRT3D(FileWriter writer)
{
writer.Write(ValueSrt3D.Scaling);
writer.Write(ValueSrt3D.Rotation);
writer.Write(ValueSrt3D.Translation);
}
private void WriteTexSrt(FileWriter writer)
{
writer.Write((uint)ValueTexSrt.Mode);
writer.Write(ValueTexSrt.Scaling);
writer.Write(ValueTexSrt.Rotation);
writer.Write(ValueTexSrt.Translation);
}
private void WriteTexSrtEx(FileWriter writer)
{
writer.Write((uint)ValueTexSrtEx.Mode);
writer.Write(ValueTexSrtEx.Scaling);
writer.Write(ValueTexSrtEx.Rotation);
writer.Write(ValueTexSrtEx.Translation);
writer.Write(ValueTexSrtEx.MatrixPointer);
}
}
public class BfresRenderInfo
{
public string Name;
public long DataOffset;
public RenderInfoType Type;
public int ArrayLength;
//Data Section by "Type"
public int[] ValueInt;
public string[] ValueString;
public float[] ValueFloat;
public RenderInfoType GetTypeWiiU(ResU.RenderInfoType type)
{
return (RenderInfoType)System.Enum.Parse(typeof(RenderInfoType), type.ToString());
}
public ResU.RenderInfoType SetTypeWiiU(RenderInfoType type)
{
return (ResU.RenderInfoType)System.Enum.Parse(typeof(ResU.RenderInfoType), type.ToString());
}
}
public class MatTexture : STGenericMatTexture
{
public string animatedTexName = "";
//Note samplers will get converted to another sampler type sometimes in the shader assign section
//Use this string if not empty for our bfres fragment shader to produce the accurate affects
//An example of a conversion maybe be like a1 - t0 so texture gets used as a transparent map/alpha texture
public string FragShaderSampler = "";
public Sampler switchSampler;
public ResUGX2.TexSampler wiiUSampler;
public float MinLod;
public float MaxLod;
public float BiasLod;
public MatTexture()
{
}
}
public class SwitchSamplerInfo
{
public ResGFX.FilterMode FilterMode;
public ResGFX.TexClamp TexClampX;
public ResGFX.TexClamp TexClampY;
public ResGFX.TexClamp TexClampZ;
}
public class WiiUSamplerInfo
{
public ResUGX2.GX2TexClamp ClampX;
public ResUGX2.GX2TexClamp ClampY;
public ResUGX2.GX2TexClamp ClampZ;
public ResUGX2.GX2TexXYFilterType MagFilter;
public ResUGX2.GX2TexXYFilterType MinFilter;
public ResUGX2.GX2TexZFilterType ZFilter;
public ResUGX2.GX2TexMipFilterType MipFilter;
public ResUGX2.GX2TexAnisoRatio MaxAnisotropicRatio;
public ResUGX2.GX2TexBorderType BorderType;
public ResUGX2.GX2CompareFunction DepthCompareFunc;
public bool DepthCompareEnabled;
public void Load(ResUGX2.TexSampler texSampler)
{
BorderType = texSampler.BorderType;
ClampX = texSampler.ClampX;
ClampY = texSampler.ClampY;
ClampZ = texSampler.ClampZ;
DepthCompareEnabled = texSampler.DepthCompareEnabled;
DepthCompareFunc = texSampler.DepthCompareFunc;
MinFilter = texSampler.MinFilter;
MipFilter = texSampler.MipFilter;
ZFilter = texSampler.ZFilter;
}
public ResUGX2.TexSampler Save(MatTexture matTex)
{
var texSampler = new ResUGX2.TexSampler();
texSampler.BorderType = BorderType;
texSampler.ClampX = ClampX;
texSampler.ClampY = ClampY;
texSampler.ClampZ = ClampZ;
texSampler.DepthCompareEnabled = DepthCompareEnabled;
texSampler.DepthCompareFunc = DepthCompareFunc;
texSampler.MinFilter = MinFilter;
texSampler.MipFilter = MipFilter;
texSampler.ZFilter = ZFilter;
texSampler.LodBias = matTex.BiasLod;
texSampler.MaxLod = matTex.MaxLod;
texSampler.MinLod = matTex.minFilter;
return texSampler;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,345 @@
using System;
using OpenTK;
using System.Collections.Generic;
using System.Linq;
using Syroot.NintenTools.NSW.Bfres;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using ResU = Syroot.NintenTools.Bfres;
using FirstPlugin;
using Switch_Toolbox.Library.NodeWrappers;
using Switch_Toolbox.Library.Forms;
namespace Bfres.Structs
{
public class FSKL : STSkeleton
{
public int[] Node_Array;
public fsklNode node;
public List<Matrix4> GetInverseMatrices()
{
List<Matrix4> matrices = new List<Matrix4>();
foreach (var bn in bones)
{
Console.WriteLine(bn.Text);
Console.WriteLine(bn.CalculateSmoothMatrix());
matrices.Add(bn.CalculateSmoothMatrix());
}
return matrices;
}
public class fsklNode : STGenericWrapper
{
public FSKL fskl;
public Skeleton Skeleton;
public ResU.Skeleton SkeletonU;
public override string ExportFilter => FileFilters.GetFilter(typeof(FSKL));
public override string ImportFilter => FileFilters.GetFilter(typeof(FSKL));
public BFRESRender GetRenderer()
{
return ((FMDL)Parent.Parent).GetRenderer();
}
public fsklNode()
{
Text = "Skeleton";
ImageKey = "skeleton";
SelectedImageKey = "skeleton";
CanDelete = false;
CanRename = false;
}
public override void LoadContextMenus()
{
ContextMenuStrip = new STContextMenuStrip();
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Import Bone", null, ImportAction, Keys.Control | Keys.I));
ContextMenuStrip.Items.Add(new ToolStripSeparator());
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Export Skeleton", null, ExportAction, Keys.Control | Keys.E));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Replace Skeleton", null, ReplaceAction, Keys.Control | Keys.R));
ContextMenuStrip.Items.Add(new ToolStripSeparator());
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Clear All Bones", null, ClearAction, Keys.Control | Keys.C));
}
public ResFile GetResFile()
{
return ((BFRESGroupNode)Parent).GetResFile();
}
public ResU.ResFile GetResFileU()
{
return ((BFRESGroupNode)Parent).GetResFileU();
}
public override void Import(string[] FileNames)
{
foreach (var FileName in FileNames)
{
string extension = System.IO.Path.GetExtension(FileName);
if (extension == ".bfbon")
{
BfresBone bn = new BfresBone();
if (SkeletonU != null)
{
ResU.Bone bone = new ResU.Bone();
bone.Import(FileName, GetResFileU());
BfresWiiU.ReadBone(bn, bone);
}
else
{
Bone bone = new Bone();
bone.Import(FileName);
BfresSwitch.ReadBone(bn, bone);
}
}
}
}
public override void Clear()
{
DialogResult dialogResult = MessageBox.Show("Are you sure you want to remove all bones? This cannot be undone!", "", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
Nodes.Clear();
}
}
public override void Export(string FileName)
{
Skeleton.Export(FileName, ((FMDL)Parent).GetResFile());
}
public override void Replace(string FileName)
{
Skeleton.Export(FileName, ((FMDL)Parent).GetResFile());
}
public override void OnClick(TreeView treeView)
{
UpdateEditor();
}
public void UpdateEditor()
{
((BFRES)Parent.Parent.Parent).LoadEditors(this);
}
}
public FSKL()
{
}
public FSKL(Skeleton skl)
{
node = new fsklNode();
node.fskl = this;
node.Skeleton = skl;
BfresSwitch.ReadSkeleton(node, skl, this);
}
public FSKL(ResU.Skeleton skl)
{
node = new fsklNode();
node.fskl = this;
node.SkeletonU = skl;
BfresWiiU.SetSkeleton(node, skl, this);
}
}
public class BfresBone : STBone
{
public bool FlagVisible = true;
public ResU.ResDict<ResU.UserData> UserDataU;
public List<UserData> UserData;
public Bone Bone;
public ResU.Bone BoneU;
public BFRESRender BFRESRender;
public BfresBone()
{
Load();
}
private void Load()
{
ImageKey = "bone";
SelectedImageKey = "bone";
ContextMenuStrip = new STContextMenuStrip();
ContextMenuStrip.Items.Add(new ToolStripMenuItem("New Child Bone", null, NewAction, Keys.Control | Keys.I));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Import Child Bone", null, ImportAction, Keys.Control | Keys.I));
ContextMenuStrip.Items.Add(new ToolStripSeparator());
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Export Bone", null, ExportAction, Keys.Control | Keys.I));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("Replace Bone", null, ReplaceAction, Keys.Control | Keys.I));
}
protected void ExportAction(object sender, EventArgs args) { Export(); }
protected void ImportAction(object sender, EventArgs args) { ImportChild(); }
protected void ReplaceAction(object sender, EventArgs args) { Replace(); }
protected void NewAction(object sender, EventArgs args) { NewChild(); }
public void CloneBaseInstance(STBone genericBone)
{
Text = genericBone.Text;
position = new float[3];
rotation = new float[4];
scale = new float[3];
position[0] = genericBone.position[0];
position[1] = genericBone.position[1];
position[2] = genericBone.position[2];
rotation[0] = genericBone.rotation[0];
rotation[1] = genericBone.rotation[1];
rotation[2] = genericBone.rotation[2];
rotation[3] = genericBone.rotation[3];
scale[0] = genericBone.scale[0];
scale[1] = genericBone.scale[1];
scale[2] = genericBone.scale[2];
RotationType = genericBone.RotationType;
parentIndex = genericBone.parentIndex;
RigidMatrixIndex = genericBone.RigidMatrixIndex;
SmoothMatrixIndex = genericBone.SmoothMatrixIndex;
}
public void SetTransforms()
{
if (BoneU != null)
{
BoneU.TransformRotateZero = (GetRotation() == Quaternion.Identity);
BoneU.TransformScaleOne = (GetScale() == Vector3.Zero);
BoneU.TransformTranslateZero = (GetPosition() == Vector3.Zero);
}
else
{
Bone.TransformRotateZero = (GetRotation() == Quaternion.FromEulerAngles(0,0,0));
Bone.TransformScaleOne = (GetScale() == Vector3.One);
Bone.TransformTranslateZero = (GetPosition() == Vector3.Zero);
}
}
public ResFile GetResFile()
{
return ((FMDL)((FSKL)skeletonParent).node.Parent).GetResFile();
}
public ResU.ResFile GetResFileU()
{
return ((FMDL)((FSKL)skeletonParent).node.Parent).GetResFileU();
}
public void NewChild()
{
BfresBone bn = new BfresBone(skeletonParent);
if (BoneU != null)
{
BoneU = new ResU.Bone();
BoneU.Name = CheckDuplicateBoneNames("NewBone");
BfresWiiU.ReadBone(bn, BoneU);
Nodes.Add(bn);
}
else
{
Bone = new Bone();
Bone.Name = CheckDuplicateBoneNames("NewBone");
BfresSwitch.ReadBone(bn, Bone);
Nodes.Add(bn);
}
}
public void ImportChild()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = FileFilters.BONE;
ofd.FileName = Text;
if (ofd.ShowDialog() == DialogResult.OK)
{
BfresBone bn = new BfresBone(skeletonParent);
if (BoneU != null)
{
BoneU = new ResU.Bone();
BoneU.Import(ofd.FileName, GetResFileU());
BoneU.Name = CheckDuplicateBoneNames(BoneU.Name);
BfresWiiU.ReadBone(bn, BoneU);
Nodes.Add(bn);
}
else
{
Bone = new Bone();
Bone.Import(ofd.FileName);
Bone.Name = CheckDuplicateBoneNames(Bone.Name);
BfresSwitch.ReadBone(bn, Bone);
Nodes.Add(bn);
}
}
}
int dupedIndex = 0;
private string CheckDuplicateBoneNames(string BoneName)
{
foreach (var bone in skeletonParent.bones)
{
if (bone.Text == BoneName)
{
BoneName = $"{BoneName}{dupedIndex++}";
return CheckDuplicateBoneNames(BoneName);
}
}
return BoneName;
}
public void Export()
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = FileFilters.BONE;
sfd.FileName = Text;
if (sfd.ShowDialog() == DialogResult.OK)
{
Bone.Export(sfd.FileName, GetResFile());
}
}
public void Replace()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = FileFilters.BONE;
if (ofd.ShowDialog() == DialogResult.OK)
{
Bone.Import(ofd.FileName);
}
Bone.Name = Text;
}
public BfresBone(STSkeleton skeleton)
{
Load();
skeletonParent = skeleton;
}
public override void OnClick(TreeView treeView)
{
UpdateEditor();
}
public void UpdateEditor()
{
((BFRES)((FSKL)skeletonParent).node.Parent.Parent.Parent).LoadEditors(this);
}
}
}

View file

@ -0,0 +1,275 @@
using System;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using FirstPlugin.Forms;
using FirstPlugin;
using Syroot.NintenTools.NSW.Bfres;
using ResU = Syroot.NintenTools.Bfres;
using Switch_Toolbox.Library.Animations;
using Switch_Toolbox.Library.NodeWrappers;
namespace Bfres.Structs
{
public class FSCN : STGenericWrapper
{
public SceneAnim SceneAnim;
public ResU.SceneAnim SceneAnimU;
public FSCN()
{
Initialize();
}
public void Initialize()
{
CanRename = true;
CanReplace = true;
CanExport = true;
CanDelete = true;
ImageKey = "materialAnim";
SelectedImageKey = "materialAnim";
ContextMenuStrip = new ContextMenuStrip();
ContextMenuStrip.Items.Add(new ToolStripMenuItem("New Camera Animation", null, NewCameraAction, Keys.Control | Keys.C));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("New Light Animation", null, NewLightAction, Keys.Control | Keys.L));
ContextMenuStrip.Items.Add(new ToolStripMenuItem("New Fog Animation", null, NewFogAction, Keys.Control | Keys.F));
LoadFileMenus(false);
}
protected void NewCameraAction(object sender, EventArgs e) { NewCameraAnim(); }
protected void NewLightAction(object sender, EventArgs e) { NewLightAnim(); }
protected void NewFogAction(object sender, EventArgs e) { NewFogAnim(); }
public void NewCameraAnim()
{
BfresCameraAnim cameraAnim = new BfresCameraAnim();
Nodes.Add(cameraAnim);
}
public void NewLightAnim()
{
BfresLightAnim lightAnim = new BfresLightAnim();
Nodes.Add(lightAnim);
}
public void NewFogAnim()
{
BfresFogAnim fogAnim = new BfresFogAnim();
Nodes.Add(fogAnim);
}
public ResFile GetResFile() {
return ((BFRESGroupNode)Parent).GetResFile();
}
public ResU.ResFile GetResFileU() {
return ((BFRESGroupNode)Parent).GetResFileU();
}
public override void OnClick(TreeView treeView) => UpdateEditor();
public void UpdateEditor(){
((BFRES)Parent.Parent.Parent).LoadEditors(this);
}
public override void Export(string FileName)
{
SceneAnim.Export(FileName, ((BFRESGroupNode)Parent).GetResFile());
}
public override void Replace(string FileName) {
Replace(FileName, GetResFile(), GetResFileU());
}
public void Replace(string FileName, ResFile resFileNX, ResU.ResFile resFileU)
{
if (resFileNX != null)
{
SceneAnim.Import(FileName);
SceneAnim.Name = Text;
}
else
{
SceneAnimU.Import(FileName, resFileU);
SceneAnimU.Name = Text;
}
}
public FSCN(ResU.SceneAnim scn) { LoadAnim(scn); }
public FSCN(SceneAnim scn) { LoadAnim(scn); }
private void LoadAnim(ResU.SceneAnim scn)
{
Initialize();
Text = scn.Name;
SceneAnimU = scn;
foreach (var cameraAnim in scn.CameraAnims.Values)
{
BfresCameraAnim anim = new BfresCameraAnim();
anim.LoadAnim(cameraAnim);
Nodes.Add(anim);
}
foreach (var lightAnim in scn.LightAnims.Values)
{
BfresLightAnim anim = new BfresLightAnim();
anim.LoadAnim(lightAnim);
Nodes.Add(anim);
}
foreach (var fogAnim in scn.FogAnims.Values)
{
BfresFogAnim anim = new BfresFogAnim();
anim.LoadAnim(fogAnim);
Nodes.Add(anim);
}
}
private void LoadAnim(SceneAnim scn)
{
Text = scn.Name;
SceneAnim = scn;
foreach (var cameraAnim in scn.CameraAnims)
{
BfresCameraAnim anim = new BfresCameraAnim();
anim.LoadAnim(cameraAnim);
Nodes.Add(anim);
}
foreach (var lightAnim in scn.LightAnims)
{
BfresLightAnim anim = new BfresLightAnim();
anim.LoadAnim(lightAnim);
Nodes.Add(anim);
}
foreach (var fogAnim in scn.FogAnims)
{
BfresFogAnim anim = new BfresFogAnim();
anim.LoadAnim(fogAnim);
Nodes.Add(anim);
}
}
public class BfresCameraAnim : CameraAnimation
{
public CameraAnim CameraAnim;
public ResU.CameraAnim CameraAnimU;
public void LoadAnim(CameraAnim anim)
{
CameraAnim = anim;
Text = anim.Name;
FrameCount = anim.FrameCount;
AspectRatio = anim.BaseData.AspectRatio;
ClipFar = anim.BaseData.ClipFar;
ClipNear = anim.BaseData.ClipNear;
FieldOfView = anim.BaseData.FieldOfView;
Position = Utils.ToVec3(anim.BaseData.Position);
Rotation = Utils.ToVec3(anim.BaseData.Rotation);
Twist = anim.BaseData.Twist;
if (anim.Flags.HasFlag(CameraAnimFlags.EulerZXY))
settings |= Settings.EulerZXY;
if (anim.Flags.HasFlag(CameraAnimFlags.Perspective))
settings |= Settings.Perspective;
for (int curve = 0; curve < anim.Curves.Count; curve++)
{
Animation.KeyGroup keyGroup = CurveHelper.CreateTrack(anim.Curves[curve]);
keyGroup.AnimDataOffset = anim.Curves[curve].AnimDataOffset;
Values.Add(new Animation.KeyGroup()
{
AnimDataOffset = keyGroup.AnimDataOffset,
Keys = keyGroup.Keys,
});
}
}
public void LoadAnim(ResU.CameraAnim anim)
{
CameraAnimU = anim;
Text = anim.Name;
FrameCount = anim.FrameCount;
AspectRatio = anim.BaseData.AspectRatio;
ClipFar = anim.BaseData.ClipFar;
ClipNear = anim.BaseData.ClipNear;
FieldOfView = anim.BaseData.FieldOfView;
Position = Utils.ToVec3(anim.BaseData.Position);
Rotation = Utils.ToVec3(anim.BaseData.Rotation);
Twist = anim.BaseData.Twist;
if (anim.Flags.HasFlag(CameraAnimFlags.EulerZXY))
settings |= Settings.EulerZXY;
if (anim.Flags.HasFlag(CameraAnimFlags.Perspective))
settings |= Settings.Perspective;
for (int curve = 0; curve < anim.Curves.Count; curve++)
{
Animation.KeyGroup keyGroup = CurveHelper.CreateTrackWiiU(anim.Curves[curve]);
keyGroup.AnimDataOffset = anim.Curves[curve].AnimDataOffset;
Values.Add(new Animation.KeyGroup()
{
AnimDataOffset = keyGroup.AnimDataOffset,
Keys = keyGroup.Keys,
});
}
}
public override void OnClick(TreeView treeview) {
UpdateEditor();
}
public void UpdateEditor() {
((BFRES)Parent.Parent.Parent.Parent).LoadEditors(this);
}
}
public class BfresLightAnim : LightAnimation
{
public void LoadAnim(LightAnim anim)
{
Text = anim.Name;
}
public void LoadAnim(ResU.LightAnim anim)
{
Text = anim.Name;
}
public override void OnClick(TreeView treeview) {
UpdateEditor();
}
public void UpdateEditor() {
((BFRES)Parent.Parent.Parent.Parent).LoadEditors(this);
}
}
public class BfresFogAnim : FogAnimation
{
public void LoadAnim(FogAnim anim)
{
Text = anim.Name;
}
public void LoadAnim(ResU.FogAnim anim)
{
Text = anim.Name;
}
public override void OnClick(TreeView treeview) {
UpdateEditor();
}
public void UpdateEditor() {
((BFRES)Parent.Parent.Parent.Parent).LoadEditors(this);
}
}
}
}

View file

@ -0,0 +1,112 @@
using System;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Animations;
using Switch_Toolbox.Library.NodeWrappers;
using FirstPlugin;
using Syroot.NintenTools.NSW.Bfres;
using ResU = Syroot.NintenTools.Bfres;
namespace Bfres.Structs
{
public class FSHA : Animation
{
public ShapeAnim ShapeAnim;
public ResU.ShapeAnim ShapeAnimU;
public FSHA()
{
ImageKey = "shapeAnimation";
SelectedImageKey = "shapeAnimation";
}
public class ShapeAnimEntry : STGenericWrapper
{
public VertexShapeAnim vertexShapeAnim;
public ResU.VertexShapeAnim vertexShapeAnimU;
public ShapeAnimEntry()
{
}
public void LoadAnim(VertexShapeAnim vertexAnim)
{
vertexShapeAnim = vertexAnim;
}
public void LoadAnim(ResU.VertexShapeAnim vertexAnim)
{
vertexShapeAnimU = vertexAnim;
}
public VertexShapeAnim SaveData()
{
vertexShapeAnim.Name = Text;
return vertexShapeAnim;
}
public ResU.VertexShapeAnim SaveDataU()
{
vertexShapeAnimU.Name = Text;
return vertexShapeAnimU;
}
}
public ResFile GetResFile() {
return ((BFRESGroupNode)Parent).GetResFile();
}
public ResU.ResFile GetResFileU() {
return ((BFRESGroupNode)Parent).GetResFileU();
}
public override void OnClick(TreeView treeView) => UpdateEditor();
public void UpdateEditor(){
((BFRES)Parent.Parent.Parent).LoadEditors(this);
}
public FSHA(ResU.ShapeAnim anim) { LoadAnim(anim); }
public FSHA(ShapeAnim anim) { LoadAnim(anim); }
private void LoadAnim(ShapeAnim shapeAnim)
{
Text = shapeAnim.Name;
ShapeAnim = shapeAnim;
}
private void LoadAnim(ResU.ShapeAnim shapeAnim)
{
Text = shapeAnim.Name;
ShapeAnimU = shapeAnim;
}
public override string ExportFilter => FileFilters.GetFilter(typeof(FSHA));
public override void Export(string FileName)
{
ShapeAnim.Export(FileName, GetResFile());
}
public override void Replace(string FileName)
{
Replace(FileName, GetResFile(), GetResFileU());
}
public void Replace(string FileName, ResFile resFileNX, ResU.ResFile resFileU)
{
if (resFileNX != null)
{
ShapeAnim.Import(FileName);
ShapeAnim.Name = Text;
}
else
{
ShapeAnimU.Import(FileName, resFileU);
ShapeAnimU.Name = Text;
}
}
}
}

View file

@ -0,0 +1,165 @@
using System.Collections.Generic;
using Switch_Toolbox.Library;
using System.Windows.Forms;
using Syroot.NintenTools.Bfres;
using FirstPlugin.Forms;
using FirstPlugin;
using Bfres.Structs;
using System;
using System.Linq;
using Switch_Toolbox.Library.Animations;
namespace Bfres.Structs
{
public class FSHU : MaterialAnimation
{
public ShaderParamAnim ShaderParamAnim;
public void Initialize()
{
ImageKey = "materialAnim";
SelectedImageKey = "materialAnim";
ContextMenuStrip = new ContextMenuStrip();
LoadFileMenus(false);
}
protected void NewAction(object sender, EventArgs e) { NewMaterialAnim(); }
public void NewMaterialAnim()
{
var mat = new MaterialAnimEntry("NewMaterialTarget");
mat.LoadMaterial(new ShaderParamMatAnim() { Name = mat.Text });
Materials.Add(mat);
}
public override void OnClick(TreeView treeView) => UpdateEditor();
public void UpdateEditor(){
((BFRES)Parent.Parent.Parent).LoadEditors(this);
}
public ResFile GetResFile() {
return ((BFRESGroupNode)Parent).GetResFileU();
}
public override void Replace(string FileName) {
Replace(FileName, GetResFile());
}
public void Replace(string FileName, ResFile resFile)
{
ShaderParamAnim = new ShaderParamAnim();
string ext = Utils.GetExtension(FileName);
if (ext == ".bfshu")
{
ShaderParamAnim.Import(FileName, resFile, ShaderParamAnimType.ShaderParameter);
LoadAnim(ShaderParamAnim, AnimationType.ShaderParam);
}
if (ext == ".bfcsh")
{
ShaderParamAnim.Import(FileName, resFile, ShaderParamAnimType.Color);
LoadAnim(ShaderParamAnim, AnimationType.Color);
}
if (ext == ".bftxp")
{
ShaderParamAnim.Import(FileName, resFile, ShaderParamAnimType.TextureSRT);
LoadAnim(ShaderParamAnim, AnimationType.TexturePattern);
}
ShaderParamAnim.Name = Text;
}
public FSHU(ShaderParamAnim anim, AnimationType type) {
LoadAnim(anim ,type);
}
public void LoadAnim(ShaderParamAnim anim, AnimationType type)
{
Initialize();
Text = anim.Name;
AnimType = type;
FrameCount = anim.FrameCount;
ShaderParamAnim = anim;
foreach (ShaderParamMatAnim matAnim in anim.ShaderParamMatAnims)
{
MaterialAnimEntry matNode = new MaterialAnimEntry(matAnim.Name);
matNode.materialAnimData = matAnim;
Materials.Add(matNode);
//Param info determines which curves to use for each param
//Add the curves and keys for left/right for interpolating after
foreach (var param in matAnim.ParamAnimInfos)
{
BfresParamAnim paramInfo = new BfresParamAnim(param.Name);
paramInfo.Type = type;
matNode.Params.Add(paramInfo);
//Get constant anims
for (int constant = 0; constant < param.ConstantCount; constant++)
{
Animation.KeyGroup keyGroup = new Animation.KeyGroup();
keyGroup.Keys.Add(new Animation.KeyFrame()
{
InterType = InterpolationType.CONSTANT,
Frame = 0,
Value = matAnim.Constants[constant].Value,
});
paramInfo.Values.Add(new Animation.KeyGroup()
{
AnimDataOffset = matAnim.Constants[constant].AnimDataOffset,
Keys = keyGroup.Keys,
});
}
for (int curve = 0; curve < param.FloatCurveCount + param.IntCurveCount; curve++)
{
int index = curve + param.BeginCurve;
Animation.KeyGroup keyGroup = CurveHelper.CreateTrackWiiU(matAnim.Curves[index]);
keyGroup.AnimDataOffset = matAnim.Curves[index].AnimDataOffset;
paramInfo.Values.Add(new Animation.KeyGroup()
{
AnimDataOffset = keyGroup.AnimDataOffset,
Keys = keyGroup.Keys,
});
}
}
}
}
public class MaterialAnimEntry : Material
{
public ShaderParamMatAnim materialAnimData;
public MaterialAnimEntry(string name) : base(name)
{
}
public void LoadMaterial(ShaderParamMatAnim data)
{
materialAnimData = data;
}
public ShaderParamMatAnim SaveData()
{
materialAnimData.Name = Text;
return materialAnimData;
}
}
public class BfresParamAnim : ParamKeyGroup
{
public BfresParamAnim(string Name)
{
Text = Name;
ImageKey = "material";
SelectedImageKey = "material";
}
}
}
}

View file

@ -0,0 +1,530 @@
using System;
using System.Linq;
using System.Collections.Generic;
using Syroot.NintenTools.NSW.Bfres;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using ResU = Syroot.NintenTools.Bfres;
using FirstPlugin;
using OpenTK;
using Switch_Toolbox.Library.Animations;
using SELib;
namespace Bfres.Structs
{
public class FSKA : Animation
{
public enum TrackType
{
XSCA = 0x4,
YSCA = 0x8,
ZSCA = 0xC,
XPOS = 0x10,
YPOS = 0x14,
ZPOS = 0x18,
XROT = 0x20,
YROT = 0x24,
ZROT = 0x28,
WROT = 0x2C,
}
public SkeletalAnim SkeletalAnim;
public ResU.SkeletalAnim SkeletalAnimU;
public FSKA()
{
Initialize();
}
public void Initialize()
{
ImageKey = "skeletonAnimation";
SelectedImageKey = "skeletonAnimation";
ContextMenuStrip = new ContextMenuStrip();
ContextMenuStrip.Items.Add(new ToolStripMenuItem("New Bone Target", null, NewAction, Keys.Control | Keys.W));
LoadFileMenus(false);
}
protected void NewAction(object sender, EventArgs e) { NewBoneAnim(); }
public void NewBoneAnim()
{
var boneAnim = new BoneAnimNode("NewBoneTarget");
if (Nodes.Count <= 0)
{
foreach (var bone in Bones)
{
Nodes.Add(bone);
}
this.Expand();
}
Nodes.Add(boneAnim);
Bones.Add(boneAnim);
if (SkeletalAnimU != null)
{
boneAnim.BoneAnimU = new ResU.BoneAnim() { Name = boneAnim.Text };
}
else
{
boneAnim.BoneAnim = new BoneAnim() { Name = boneAnim.Text };
}
}
public ResFile GetResFile() {
return ((BFRESGroupNode)Parent).GetResFile();
}
public ResU.ResFile GetResFileU() {
return ((BFRESGroupNode)Parent).GetResFileU();
}
public override void OnClick(TreeView treeView) => UpdateEditor();
public override void OnDoubleMouseClick(TreeView treeview)
{
if (Nodes.Count <= 0)
{
foreach (var bone in Bones)
{
Nodes.Add(bone);
}
this.Expand();
}
}
public void UpdateEditor() {
((BFRES)Parent.Parent.Parent).LoadEditors(this);
}
public override string ExportFilter => FileFilters.GetFilter(typeof(FSKA));
public override string ReplaceFilter => FileFilters.GetFilter(typeof(FSKA));
public override void Export(string FileName)
{
string ext = Utils.GetExtension(FileName);
if (ext == ".bfska")
{
if (GetResFileU() != null)
{
SkeletalAnimU.Export(FileName, GetResFileU());
}
else
{
SkeletalAnim.Export(FileName, GetResFile());
}
}
else if (ext == ".seanim")
{
STSkeleton skeleton = null;
var viewport = LibraryGUI.Instance.GetActiveViewport();
if (viewport != null)
{
foreach (var drawable in viewport.scene.objects)
{
if (drawable is STSkeleton)
{
foreach (var bone in Bones)
{
var animBone = ((STSkeleton)drawable).GetBone(bone.Text);
if (animBone != null)
skeleton = (STSkeleton)drawable;
}
}
}
}
else
{
foreach (var model in ((BFRES)Parent.Parent.Parent.Parent).BFRESRender.models)
{
foreach (var bone in Bones)
{
var animBone = model.Skeleton.GetBone(bone.Text);
if (animBone != null)
skeleton = model.Skeleton;
}
}
}
if (skeleton != null)
SEANIM.SaveAnimation(FileName, this, skeleton);
else
throw new Exception("No skeleton found to assign!");
}
}
public override void Replace(string FileName) {
Replace(FileName, GetResFile(), GetResFileU());
}
public void Replace(string FileName, ResFile resFileNX, ResU.ResFile resFileU)
{
string ext = Utils.GetExtension(FileName);
if (ext == ".bfska")
{
if (GetResFileU() != null)
{
SkeletalAnimU.Import(FileName, GetResFileU());
SkeletalAnimU.Name = Text;
LoadAnim(SkeletalAnimU);
}
else
{
SkeletalAnim.Import(FileName);
SkeletalAnim.Name = Text;
LoadAnim(SkeletalAnim);
}
}
else if (ext == ".seanim")
{
FromSeanim(FileName);
}
}
public FSKA(ResU.SkeletalAnim ska) { LoadAnim(ska); }
public FSKA(SkeletalAnim ska) { LoadAnim(ska); }
public override void OpenAnimationData()
{
if (SkeletalAnimU != null)
LoadAnimData(SkeletalAnimU);
else
LoadAnimData(SkeletalAnim);
}
private void LoadAnimData(SkeletalAnim ska)
{
Nodes.Clear();
Bones.Clear();
foreach (BoneAnim bn in ska.BoneAnims)
{
BoneAnimNode bone = new BoneAnimNode(bn.Name);
bone.BoneAnim = bn;
bone.UseSegmentScaleCompensate = bn.ApplySegmentScaleCompensate;
Bones.Add(bone);
if (ska.FlagsRotate == SkeletalAnimFlagsRotate.EulerXYZ)
bone.RotType = Animation.RotationType.EULER;
else
bone.RotType = Animation.RotationType.QUATERNION;
if (bn.UseScale)
{
bone.XSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Scale.X, IsKeyed = true });
bone.YSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Scale.Y, IsKeyed = true });
bone.ZSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Scale.Z, IsKeyed = true });
}
if (bn.UseRotation)
{
bone.XROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.X, IsKeyed = true });
bone.YROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.Y, IsKeyed = true });
bone.ZROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.Z, IsKeyed = true });
bone.WROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.W, IsKeyed = true });
}
if (bn.UseTranslation)
{
bone.XPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Translate.X, IsKeyed = true });
bone.YPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Translate.Y, IsKeyed = true });
bone.ZPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Translate.Z, IsKeyed = true });
}
for (int curve = 0; curve < bn.Curves.Count; curve++)
{
Animation.KeyGroup keyGroup = CurveHelper.CreateTrack(bn.Curves[curve]);
keyGroup.AnimDataOffset = bn.Curves[curve].AnimDataOffset;
switch (keyGroup.AnimDataOffset)
{
case (int)TrackType.XPOS: bone.XPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YPOS: bone.YPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZPOS: bone.ZPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.XROT: bone.XROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YROT: bone.YROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZROT: bone.ZROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.WROT: bone.WROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.XSCA: bone.XSCA.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YSCA: bone.YSCA.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZSCA: bone.ZSCA.Keys.AddRange(keyGroup.Keys); break;
default: throw new Exception("Unknown Anim Offset " + keyGroup.AnimDataOffset);
}
}
}
}
private void LoadAnimData(ResU.SkeletalAnim ska)
{
Nodes.Clear();
Bones.Clear();
foreach (ResU.BoneAnim bn in ska.BoneAnims)
{
BoneAnimNode bone = new BoneAnimNode(bn.Name);
bone.BoneAnimU = bn;
bone.UseSegmentScaleCompensate = bn.ApplySegmentScaleCompensate;
Bones.Add(bone);
if (ska.FlagsRotate == ResU.SkeletalAnimFlagsRotate.EulerXYZ)
bone.RotType = Animation.RotationType.EULER;
else
bone.RotType = Animation.RotationType.QUATERNION;
if (bn.FlagsBase.HasFlag(ResU.BoneAnimFlagsBase.Scale))
{
bone.XSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Scale.X, IsKeyed = true });
bone.YSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Scale.Y, IsKeyed = true });
bone.ZSCA.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Scale.Z, IsKeyed = true });
}
if (bn.FlagsBase.HasFlag(ResU.BoneAnimFlagsBase.Rotate))
{
bone.XROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.X, IsKeyed = true });
bone.YROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.Y, IsKeyed = true });
bone.ZROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.Z, IsKeyed = true });
bone.WROT.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Rotate.W, IsKeyed = true });
}
if (bn.FlagsBase.HasFlag(ResU.BoneAnimFlagsBase.Translate))
{
bone.XPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Translate.X, IsKeyed = true });
bone.YPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Translate.Y, IsKeyed = true });
bone.ZPOS.Keys.Add(new KeyFrame() { Frame = 0, Value = bn.BaseData.Translate.Z, IsKeyed = true });
}
for (int curve = 0; curve < bn.Curves.Count; curve++)
{
Animation.KeyGroup keyGroup = CurveHelper.CreateTrackWiiU(bn.Curves[curve]);
keyGroup.AnimDataOffset = bn.Curves[curve].AnimDataOffset;
switch (keyGroup.AnimDataOffset)
{
case (int)TrackType.XPOS: bone.XPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YPOS: bone.YPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZPOS: bone.ZPOS.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.XROT: bone.XROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YROT: bone.YROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZROT: bone.ZROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.WROT: bone.WROT.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.XSCA: bone.XSCA.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.YSCA: bone.YSCA.Keys.AddRange(keyGroup.Keys); break;
case (int)TrackType.ZSCA: bone.ZSCA.Keys.AddRange(keyGroup.Keys); break;
default: throw new Exception("Unknown Anim Offset " + keyGroup.AnimDataOffset);
}
}
}
}
private void LoadAnim(ResU.SkeletalAnim ska)
{
Text = ska.Name;
FrameCount = ska.FrameCount;
SkeletalAnimU = ska;
Initialize();
}
private void LoadAnim(SkeletalAnim ska)
{
Text = ska.Name;
FrameCount = ska.FrameCount;
SkeletalAnim = ska;
Initialize();
}
public void FromSeanim(string FileName)
{
SEAnim anim = SEAnim.Read(FileName);
if (GetResFileU() != null)
{
SkeletalAnimU = new ResU.SkeletalAnim();
SkeletalAnimU.FrameCount = anim.FrameCount;
SkeletalAnimU.FlagsScale = ResU.SkeletalAnimFlagsScale.Maya;
SkeletalAnimU.FlagsRotate = ResU.SkeletalAnimFlagsRotate.EulerXYZ;
SkeletalAnimU.Loop = anim.Looping;
SkeletalAnimU.Name = System.IO.Path.GetFileNameWithoutExtension(FileName);
SkeletalAnimU.Path = "";
}
else
{
SkeletalAnim = new SkeletalAnim();
SkeletalAnim.FrameCount = anim.FrameCount;
SkeletalAnim.FlagsScale = SkeletalAnimFlagsScale.Maya;
SkeletalAnim.FlagsRotate = SkeletalAnimFlagsRotate.EulerXYZ;
SkeletalAnim.Loop = anim.Looping;
SkeletalAnim.Name = System.IO.Path.GetFileNameWithoutExtension(FileName);
SkeletalAnim.Path = "";
}
for (int i = 0; i < anim.Bones.Count; i++)
{
if (GetResFileU() != null)
{
var BoneAnimU = new ResU.BoneAnim();
BoneAnimU.Name = anim.Bones[i];
SkeletalAnimU.BoneAnims.Add(BoneAnimU);
SkeletalAnimU.BindIndices[i] = ushort.MaxValue;
bool IsRoot = false;
if (!IsRoot)
{
BoneAnimU.ApplyIdentity = false;
BoneAnimU.ApplyRotateTranslateZero = false;
BoneAnimU.ApplyRotateZero = false;
BoneAnimU.ApplyScaleOne = true;
BoneAnimU.ApplyScaleVolumeOne = true;
BoneAnimU.ApplyScaleUniform = true;
BoneAnimU.ApplySegmentScaleCompensate = true;
BoneAnimU.ApplyTranslateZero = false;
}
else
{
BoneAnimU.ApplyIdentity = true;
BoneAnimU.ApplyRotateTranslateZero = true;
BoneAnimU.ApplyRotateZero = true;
BoneAnimU.ApplyScaleOne = true;
BoneAnimU.ApplyScaleVolumeOne = true;
BoneAnimU.ApplyScaleUniform = true;
BoneAnimU.ApplySegmentScaleCompensate = false;
BoneAnimU.ApplyTranslateZero = true;
}
}
else
{
var BoneAnim = new BoneAnim();
BoneAnim.Name = anim.Bones[i];
SkeletalAnim.BoneAnims.Add(BoneAnim);
SkeletalAnim.BindIndices[i] = ushort.MaxValue;
//Set base data and curves
var baseData = new BoneAnimData();
if (anim.AnimationPositionKeys.ContainsKey(anim.Bones[i]) &&
anim.AnimationPositionKeys[anim.Bones[i]].Count > 0)
{
BoneAnim.FlagsBase |= BoneAnimFlagsBase.Translate;
var keys = anim.AnimationPositionKeys[anim.Bones[i]];
var data = (SELib.Utilities.Vector3)keys[0].Data;
baseData.Translate = new Syroot.Maths.Vector3F((float)data.X, (float)data.Y, (float)data.Z);
if (keys.Count > 1)
{
AnimCurve curve = new AnimCurve();
BoneAnim.Curves.Add(curve);
CreateCurveData(curve, keys);
}
}
if (anim.AnimationRotationKeys.ContainsKey(anim.Bones[i]) &&
anim.AnimationRotationKeys[anim.Bones[i]].Count > 0)
{
BoneAnim.FlagsBase |= BoneAnimFlagsBase.Rotate;
var keys = anim.AnimationPositionKeys[anim.Bones[i]];
var data = (SELib.Utilities.Quaternion)keys[0].Data;
baseData.Rotate = new Syroot.Maths.Vector4F((float)data.X, (float)data.Y, (float)data.Z, (float)data.W);
if (keys.Count > 1)
{
AnimCurve curve = new AnimCurve();
BoneAnim.Curves.Add(curve);
CreateCurveData(curve, keys);
}
}
if (anim.AnimationScaleKeys.ContainsKey(anim.Bones[i]) &&
anim.AnimationScaleKeys[anim.Bones[i]].Count > 0)
{
BoneAnim.FlagsBase |= BoneAnimFlagsBase.Scale;
var keys = anim.AnimationPositionKeys[anim.Bones[i]];
var data = (SELib.Utilities.Vector3)keys[0].Data;
baseData.Scale = new Syroot.Maths.Vector3F((float)data.X, (float)data.Y, (float)data.Z);
if (keys.Count > 1)
{
AnimCurve curve = new AnimCurve();
BoneAnim.Curves.Add(curve);
CreateCurveData(curve, keys);
}
}
//Set transforms
bool IsRoot = false;
if (!IsRoot)
{
BoneAnim.ApplyIdentity = false;
BoneAnim.ApplyRotateTranslateZero = false;
BoneAnim.ApplyRotateZero = false;
BoneAnim.ApplyScaleOne = true;
BoneAnim.ApplyScaleVolumeOne = true;
BoneAnim.ApplyScaleUniform = true;
BoneAnim.ApplySegmentScaleCompensate = true;
BoneAnim.ApplyTranslateZero = false;
}
else
{
BoneAnim.ApplyIdentity = true;
BoneAnim.ApplyRotateTranslateZero = true;
BoneAnim.ApplyRotateZero = true;
BoneAnim.ApplyScaleOne = true;
BoneAnim.ApplyScaleVolumeOne = true;
BoneAnim.ApplyScaleUniform = true;
BoneAnim.ApplySegmentScaleCompensate = false;
BoneAnim.ApplyTranslateZero = true;
}
}
}
for (int frame = 0; frame < anim.FrameCount; frame++)
{
}
}
private void CreateCurveData(AnimCurve curve, List<SEAnimFrame> keys)
{
for (int k = 0; k < keys.Count; k++)
{
}
}
public class BoneAnimNode : KeyNode
{
public override void OnClick(TreeView treeView) => UpdateEditor();
public void UpdateEditor()
{
((BFRES)Parent.Parent.Parent.Parent).LoadEditors(this);
}
public BoneAnim BoneAnim;
public ResU.BoneAnim BoneAnimU;
public ResU.BoneAnim SaveDataU()
{
BoneAnimU.Name = Text;
return BoneAnimU;
}
public BoneAnim SaveData()
{
BoneAnim.Name = Text;
return BoneAnim;
}
public BoneAnimNode(string bname) : base(bname)
{
}
}
}
}

View file

@ -0,0 +1,575 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Forms;
using Syroot.NintenTools.Bfres;
using Syroot.NintenTools.Bfres.GX2;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using Switch_Toolbox.Library.IO;
using FirstPlugin;
namespace Bfres.Structs
{
public class FTEX : STGenericTexture
{
public override TEX_FORMAT[] SupportedFormats
{
get
{
return new TEX_FORMAT[]
{
TEX_FORMAT.BC1_UNORM,
TEX_FORMAT.BC1_UNORM_SRGB,
TEX_FORMAT.BC2_UNORM,
TEX_FORMAT.BC2_UNORM_SRGB,
TEX_FORMAT.BC3_UNORM,
TEX_FORMAT.BC3_UNORM_SRGB,
TEX_FORMAT.BC4_UNORM,
TEX_FORMAT.BC4_SNORM,
TEX_FORMAT.BC5_UNORM,
TEX_FORMAT.BC5_SNORM,
TEX_FORMAT.B5G5R5A1_UNORM,
TEX_FORMAT.B5G6R5_UNORM,
TEX_FORMAT.B8G8R8A8_UNORM_SRGB,
TEX_FORMAT.B8G8R8A8_UNORM,
TEX_FORMAT.R10G10B10A2_UNORM,
TEX_FORMAT.R16_UNORM,
TEX_FORMAT.B4G4R4A4_UNORM,
TEX_FORMAT.B5_G5_R5_A1_UNORM,
TEX_FORMAT.R8G8B8A8_UNORM_SRGB,
TEX_FORMAT.R8G8B8A8_UNORM,
TEX_FORMAT.R8_UNORM,
TEX_FORMAT.R8G8_UNORM,
TEX_FORMAT.R32G8X24_FLOAT,
};
}
}
public override bool CanEdit { get; set; } = false;
public int format;
public Texture texture;
public FTEX()
{
CanReplace = true;
CanDelete = true;
CanEdit = true;
CanExport = true;
}
public FTEX(Texture tex) { Read(tex); }
public FTEX(string name) { Text = name; }
//For determining mip map file for botw (Tex2)
public string GetFilePath()
{
if (Parent == null)
return "";
return ((BFRES)Parent.Parent).FilePath;
}
public override string ExportFilter => FileFilters.GetFilter(typeof(FTEX));
public override string ImportFilter => FileFilters.GetFilter(typeof(FTEX));
public override void Rename()
{
RenameDialog dialog = new RenameDialog();
dialog.SetString(Text);
if (dialog.ShowDialog() == DialogResult.OK)
{
//Update dictionary key
((BFRESGroupNode)Parent).ResourceNodes.Remove(Text);
Text = dialog.textBox1.Text;
((BFRESGroupNode)Parent).ResourceNodes.Add(Text, this);
}
}
public override void Delete()
{
((BFRESGroupNode)Parent).RemoveChild(this);
LibraryGUI.Instance.UpdateViewport(); //Update texture display
}
public override void Export(string FileName) => Export(FileName);
public static GTXImporterSettings SetImporterSettings(Image image, string name)
{
var importer = new GTXImporterSettings();
importer.LoadBitMap(image, name);
return importer;
}
public static GTXImporterSettings SetImporterSettings(string name)
{
var importer = new GTXImporterSettings();
string ext = System.IO.Path.GetExtension(name);
ext = ext.ToLower();
switch (ext)
{
case ".dds":
case ".dds2":
importer.LoadDDS(name);
break;
default:
importer.LoadBitMap(name);
break;
}
return importer;
}
public void ReplaceImage(Image image, string FileName)
{
GTXImporterSettings setting = SetImporterSettings(image, FileName);
GTXTextureImporter importer = new GTXTextureImporter();
if (Tex2Swizzle != 0)
setting.swizzle = Tex2Swizzle;
setting.swizzle = 0;
importer.LoadSetting(setting);
if (importer.ShowDialog() == DialogResult.OK)
{
Cursor.Current = Cursors.WaitCursor;
if (setting.GenerateMipmaps)
{
setting.DataBlockOutput.Clear();
setting.DataBlockOutput.Add(setting.GenerateMips());
}
if (setting.DataBlockOutput != null)
{
var surface = setting.CreateGx2Texture(setting.DataBlockOutput[0]);
var tex = FromGx2Surface(surface, setting);
if (texture == null)
texture = new Texture();
UpdateTex(tex);
texture.Name = Text;
IsEdited = true;
Read(texture);
LoadOpenGLTexture();
}
else
{
MessageBox.Show("Something went wrong???");
}
}
if (IsEditorActive())
UpdateEditor();
}
public override void Replace(string FileName)
{
string ext = System.IO.Path.GetExtension(FileName);
ext = ext.ToLower();
if (ext == ".bftex")
{
texture.Import(FileName, ((BFRESGroupNode)Parent).GetResFileU());
texture.Name = Text;
IsEdited = true;
Read(texture);
if (IsEditorActive())
UpdateEditor();
return;
}
GTXImporterSettings setting = SetImporterSettings(FileName);
GTXTextureImporter importer = new GTXTextureImporter();
if (Tex2Swizzle != 0)
setting.swizzle = Tex2Swizzle;
setting.swizzle = 0;
importer.LoadSetting(setting);
if (ext == ".dds")
{
if (setting.DataBlockOutput != null)
{
var surface = setting.CreateGx2Texture(setting.DataBlockOutput[0]);
var tex = FromGx2Surface(surface, setting);
UpdateTex(tex);
texture.Name = Text;
IsEdited = true;
Read(texture);
LoadOpenGLTexture();
}
}
else
{
if (importer.ShowDialog() == DialogResult.OK)
{
Cursor.Current = Cursors.WaitCursor;
if (setting.GenerateMipmaps)
{
setting.DataBlockOutput.Clear();
setting.DataBlockOutput.Add(setting.GenerateMips());
}
if (setting.DataBlockOutput != null)
{
var surface = setting.CreateGx2Texture(setting.DataBlockOutput[0]);
var tex = FromGx2Surface(surface, setting);
UpdateTex(tex);
texture.Name = Text;
IsEdited = true;
Read(texture);
LoadOpenGLTexture();
}
else
{
MessageBox.Show("Something went wrong???");
}
}
}
if (IsEditorActive())
UpdateEditor();
}
public void UpdateTex(Texture tex)
{
texture.Name = tex.Name;
texture.Data = tex.Data;
texture.MipData = tex.MipData;
texture.MipOffsets = tex.MipOffsets;
texture.Pitch = tex.Pitch;
texture.Swizzle = tex.Swizzle;
texture.Width = tex.Width;
texture.Height = tex.Height;
texture.AAMode = tex.AAMode;
texture.Alignment = tex.Alignment;
texture.ArrayLength = tex.ArrayLength;
texture.CompSelR = tex.CompSelR;
texture.CompSelG = tex.CompSelG;
texture.CompSelB = tex.CompSelB;
texture.CompSelA = tex.CompSelA;
texture.Depth = tex.Depth;
texture.Dim = tex.Dim;
texture.Format = tex.Format;
texture.Path = tex.Path;
texture.TileMode = tex.TileMode;
texture.Use = tex.Use;
texture.ViewMipCount = tex.ViewMipCount;
texture.ViewMipFirst = tex.ViewMipFirst;
texture.ViewSliceCount = tex.ViewSliceCount;
texture.ViewSliceFirst = tex.ViewSliceFirst;
texture.Regs = tex.Regs;
texture.MipCount = tex.MipCount;
}
//We reuse GX2 data as it's the same thing
public Texture FromGx2Surface(GTX.GX2Surface surf, GTXImporterSettings settings)
{
Texture tex = new Texture();
tex.Name = settings.TexName;
tex.Path = "";
tex.AAMode = (GX2AAMode)surf.aa;
tex.Alignment = (uint)surf.alignment;
tex.ArrayLength = 1;
tex.Data = surf.data;
tex.MipData = surf.mipData;
tex.Format = (GX2SurfaceFormat)surf.format;
tex.Dim = (GX2SurfaceDim)surf.dim;
tex.Use = (GX2SurfaceUse)surf.use;
tex.TileMode = (GX2TileMode)surf.tileMode;
tex.Swizzle = surf.swizzle;
tex.Pitch = surf.pitch;
tex.Depth = surf.depth;
tex.MipCount = surf.numMips;
tex.ViewMipCount = surf.numMips;
tex.ViewSliceCount = 1;
tex.MipOffsets = new uint[13];
for (int i = 0; i < 13; i++)
{
if (i < surf.mipOffset.Length)
tex.MipOffsets[i] = surf.mipOffset[i];
}
tex.Height = surf.height;
tex.Width = surf.width;
tex.Regs = new uint[5];
tex.ArrayLength = 1;
var channels = SetChannelsByFormat((GX2SurfaceFormat)surf.format);
tex.CompSelR = channels[0];
tex.CompSelG = channels[1];
tex.CompSelB = channels[2];
tex.CompSelA = channels[3];
tex.UserData = new ResDict<UserData>();
return tex;
}
public uint Tex2Swizzle = 0;
public void Read(Texture tex)
{
CanReplace = true;
CanDelete = true;
CanEdit = false;
CanExport = true;
ImageKey = "Texture";
SelectedImageKey = "Texture";
Text = tex.Name;
texture = tex;
Width = tex.Width;
Height = tex.Height;
Format = ConvertFromGx2Format(tex.Format);
ArrayCount = tex.ArrayLength;
if (tex.ArrayLength == 0)
ArrayCount = tex.Depth; //Some older bfres don't use array length????
MipCount = tex.MipCount;
if (tex.MipData == null || tex.MipData.Length <= 0)
MipCount = 1;
}
public override void SetImageData(Bitmap bitmap, int ArrayLevel)
{
throw new NotImplementedException("Cannot set image data! Operation not implemented!");
}
public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0)
{
format = (int)texture.Format;
int swizzle = (int)texture.Swizzle;
int pitch = (int)texture.Pitch;
uint bpp = GTX.surfaceGetBitsPerPixel((uint)format) >> 3;
GTX.GX2Surface surf = new GTX.GX2Surface();
surf.bpp = bpp;
surf.height = texture.Height;
surf.width = texture.Width;
surf.aa = (uint)texture.AAMode;
surf.alignment = texture.Alignment;
surf.depth = texture.Depth;
surf.dim = (uint)texture.Dim;
surf.format = (uint)texture.Format;
surf.use = (uint)texture.Use;
surf.pitch = texture.Pitch;
surf.data = texture.Data;
surf.numMips = texture.MipCount;
surf.mipOffset = texture.MipOffsets;
surf.mipData = texture.MipData;
surf.tileMode = (uint)texture.TileMode;
surf.swizzle = texture.Swizzle;
surf.numArray = texture.ArrayLength;
//Determine tex2 botw files to get mip maps
string Tex1 = GetFilePath();
if (!IsEdited && Tex1 != null && Tex1.Contains(".Tex1"))
{
string Tex2 = Tex1.Replace(".Tex1", ".Tex2");
Console.WriteLine(Tex2);
if (System.IO.File.Exists(Tex2))
{
ResFile resFile2;
if (Tex2.EndsWith(".sbfres"))
{
resFile2 = new ResFile(new System.IO.MemoryStream(
EveryFileExplorer.YAZ0.Decompress(Tex2)));
}
else
{
resFile2 = new ResFile(Tex2);
}
if (resFile2.Textures.ContainsKey(texture.Name))
{
texture.MipData = resFile2.Textures[texture.Name].MipData;
texture.MipOffsets = resFile2.Textures[texture.Name].MipOffsets;
surf.mipData = resFile2.Textures[texture.Name].MipData;
surf.mipOffset = resFile2.Textures[texture.Name].MipOffsets;
Tex2Swizzle = resFile2.Textures[texture.Name].Swizzle;
}
}
}
if (surf.mipData == null)
surf.numMips = 1;
var surfaces = GTX.Decode(surf);
return surfaces[ArrayLevel][MipLevel];
}
public static GX2SurfaceFormat ConvertToGx2Format(TEX_FORMAT texFormat)
{
switch (texFormat)
{
case TEX_FORMAT.BC1_UNORM: return GX2SurfaceFormat.T_BC1_UNorm;
case TEX_FORMAT.BC1_UNORM_SRGB: return GX2SurfaceFormat.T_BC1_SRGB;
case TEX_FORMAT.BC2_UNORM: return GX2SurfaceFormat.T_BC2_UNorm;
case TEX_FORMAT.BC2_UNORM_SRGB: return GX2SurfaceFormat.T_BC2_SRGB;
case TEX_FORMAT.BC3_UNORM: return GX2SurfaceFormat.T_BC3_UNorm;
case TEX_FORMAT.BC3_UNORM_SRGB: return GX2SurfaceFormat.T_BC3_SRGB;
case TEX_FORMAT.BC4_UNORM: return GX2SurfaceFormat.T_BC4_UNorm;
case TEX_FORMAT.BC4_SNORM: return GX2SurfaceFormat.T_BC4_SNorm;
case TEX_FORMAT.BC5_UNORM: return GX2SurfaceFormat.T_BC5_UNorm;
case TEX_FORMAT.BC5_SNORM: return GX2SurfaceFormat.T_BC5_SNorm;
case TEX_FORMAT.B5G5R5A1_UNORM: return GX2SurfaceFormat.TC_R5_G5_B5_A1_UNorm;
case TEX_FORMAT.B4G4R4A4_UNORM: return GX2SurfaceFormat.TC_R4_G4_B4_A4_UNorm;
case TEX_FORMAT.B5G6R5_UNORM: return GX2SurfaceFormat.TCS_R5_G6_B5_UNorm;
case TEX_FORMAT.R8G8B8A8_UNORM: return GX2SurfaceFormat.TCS_R8_G8_B8_A8_UNorm;
case TEX_FORMAT.R8G8B8A8_UNORM_SRGB: return GX2SurfaceFormat.TCS_R8_G8_B8_A8_SRGB;
case TEX_FORMAT.R10G10B10A2_UNORM: return GX2SurfaceFormat.TCS_R10_G10_B10_A2_UNorm;
case TEX_FORMAT.R11G11B10_FLOAT: return GX2SurfaceFormat.TC_R11_G11_B10_Float;
case TEX_FORMAT.R16_UNORM: return GX2SurfaceFormat.TCD_R16_UNorm;
case TEX_FORMAT.R32_FLOAT: return GX2SurfaceFormat.TCD_R32_Float;
case TEX_FORMAT.R8G8_UNORM: return GX2SurfaceFormat.TC_R8_G8_UNorm;
case TEX_FORMAT.R8_UNORM: return GX2SurfaceFormat.TC_R8_UNorm;
default:
throw new Exception($"Cannot convert format {texFormat}");
}
}
public static TEX_FORMAT ConvertFromGx2Format(GX2SurfaceFormat GX2Format)
{
switch (GX2Format)
{
case GX2SurfaceFormat.T_BC1_UNorm: return TEX_FORMAT.BC1_UNORM;
case GX2SurfaceFormat.T_BC1_SRGB: return TEX_FORMAT.BC1_UNORM_SRGB;
case GX2SurfaceFormat.T_BC2_UNorm: return TEX_FORMAT.BC2_UNORM;
case GX2SurfaceFormat.T_BC2_SRGB: return TEX_FORMAT.BC2_UNORM_SRGB;
case GX2SurfaceFormat.T_BC3_UNorm: return TEX_FORMAT.BC3_UNORM;
case GX2SurfaceFormat.T_BC3_SRGB: return TEX_FORMAT.BC3_UNORM;
case GX2SurfaceFormat.T_BC4_UNorm: return TEX_FORMAT.BC4_UNORM;
case GX2SurfaceFormat.T_BC4_SNorm: return TEX_FORMAT.BC4_SNORM;
case GX2SurfaceFormat.T_BC5_UNorm: return TEX_FORMAT.BC5_UNORM;
case GX2SurfaceFormat.T_BC5_SNorm: return TEX_FORMAT.BC5_SNORM;
case GX2SurfaceFormat.TC_R5_G5_B5_A1_UNorm: return TEX_FORMAT.B5G5R5A1_UNORM;
case GX2SurfaceFormat.TC_A1_B5_G5_R5_UNorm: return TEX_FORMAT.B5G5R5A1_UNORM;
case GX2SurfaceFormat.TC_R4_G4_B4_A4_UNorm: return TEX_FORMAT.B4G4R4A4_UNORM;
case GX2SurfaceFormat.TCS_R5_G6_B5_UNorm: return TEX_FORMAT.B5G6R5_UNORM;
case GX2SurfaceFormat.TCS_R8_G8_B8_A8_SRGB: return TEX_FORMAT.R8G8B8A8_UNORM;
case GX2SurfaceFormat.TCS_R8_G8_B8_A8_UNorm: return TEX_FORMAT.R8G8B8A8_UNORM;
case GX2SurfaceFormat.TCS_R10_G10_B10_A2_UNorm: return TEX_FORMAT.R10G10B10A2_UNORM;
case GX2SurfaceFormat.TC_R11_G11_B10_Float: return TEX_FORMAT.R11G11B10_FLOAT;
case GX2SurfaceFormat.TCD_R16_UNorm: return TEX_FORMAT.R16_UNORM;
case GX2SurfaceFormat.TCD_R32_Float: return TEX_FORMAT.R32_FLOAT;
case GX2SurfaceFormat.T_R4_G4_UNorm: return TEX_FORMAT.B4G4R4A4_UNORM;
case GX2SurfaceFormat.TC_R8_G8_UNorm: return TEX_FORMAT.R8G8_UNORM;
case GX2SurfaceFormat.TC_R8_UNorm: return TEX_FORMAT.R8_UNORM;
case GX2SurfaceFormat.Invalid: throw new Exception("Invalid Format");
default:
throw new Exception($"Cannot convert format {GX2Format}");
}
}
public static GX2CompSel[] SetChannelsByFormat(GX2SurfaceFormat Format)
{
GX2CompSel[] channels = new GX2CompSel[4];
switch (Format)
{
case GX2SurfaceFormat.T_BC5_UNorm:
case GX2SurfaceFormat.T_BC5_SNorm:
channels[0] = GX2CompSel.ChannelR;
channels[1] = GX2CompSel.ChannelG;
channels[2] = GX2CompSel.Always0;
channels[3] = GX2CompSel.Always1;
break;
case GX2SurfaceFormat.T_BC4_SNorm:
case GX2SurfaceFormat.T_BC4_UNorm:
channels[0] = GX2CompSel.ChannelR;
channels[1] = GX2CompSel.ChannelR;
channels[2] = GX2CompSel.ChannelR;
channels[3] = GX2CompSel.ChannelR;
break;
default:
channels[0] = GX2CompSel.ChannelR;
channels[1] = GX2CompSel.ChannelG;
channels[2] = GX2CompSel.ChannelB;
channels[3] = GX2CompSel.ChannelA;
break;
}
return channels;
}
public void Export(string FileName, bool ExportSurfaceLevel = false,
bool ExportMipMapLevel = false, int SurfaceLevel = 0, int MipLevel = 0)
{
string ext = System.IO.Path.GetExtension(FileName);
ext = ext.ToLower();
switch (ext)
{
case ".bftex":
SaveBinaryTexture(FileName);
break;
case ".dds":
case ".dds2":
SaveDDS(FileName);
break;
default:
SaveBitMap(FileName);
break;
}
}
internal void SaveBinaryTexture(string FileName)
{
texture.Export(FileName, ((BFRESGroupNode)Parent).GetResFileU());
}
private bool IsEditorActive()
{
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.Instance.GetActiveContent(typeof(ImageEditorBase));
if (editor == null)
return false;
else
return true;
}
public override void OnClick(TreeView treeView)
{
UpdateEditor();
}
public void UpdateEditor()
{
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.Instance.GetActiveContent(typeof(ImageEditorBase));
if (editor == null)
{
editor = new ImageEditorBase();
editor.Dock = DockStyle.Fill;
LibraryGUI.Instance.LoadEditor(editor);
}
editor.Text = Text;
editor.LoadProperties(this.texture);
editor.LoadImage(this);
if (texture.UserData != null)
{
UserDataEditor userEditor = (UserDataEditor)editor.GetActiveTabEditor(typeof(UserDataEditor));
if (userEditor == null)
{
userEditor = new UserDataEditor();
userEditor.Name = "User Data";
editor.AddCustomControl(userEditor, typeof(UserDataEditor));
}
userEditor.LoadUserData(texture.UserData);
}
}
}
}

View file

@ -0,0 +1,242 @@
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using FirstPlugin;
using FirstPlugin.Forms;
using Syroot.NintenTools.Bfres;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Animations;
namespace Bfres.Structs
{
public class FTXP : MaterialAnimation
{
public TexPatternAnim TexPatternAnim;
public override void OnClick(TreeView treeView) => UpdateEditor();
public void UpdateEditor() {
((BFRES)Parent.Parent.Parent).LoadEditors(this);
}
public ResFile GetResFile() {
return ((BFRESGroupNode)Parent).GetResFileU();
}
public FTXP(TexPatternAnim anim) { LoadAnim(anim); }
public void UpdateMaterialBinds()
{
ushort[] binds = new ushort[TexPatternAnim.TexPatternMatAnims.Count];
for (int i = 0; i < binds.Length; i++)
binds[i] = ushort.MaxValue;
TexPatternAnim.BindIndices = binds;
}
private void LoadAnim(TexPatternAnim anim)
{
CanReplace = true;
CanExport = true;
CanDelete = true;
CanRename = true;
Text = anim.Name;
TexPatternAnim = anim;
FrameCount = anim.FrameCount;
if (anim.TextureRefNames != null)
{
foreach (var tex in anim.TextureRefNames)
Textures.Add(tex.Name);
}
if (anim.TextureRefs != null)
{
foreach (var tex in anim.TextureRefs)
Textures.Add(tex.Key);
}
foreach (TexPatternMatAnim matanim in anim.TexPatternMatAnims)
{
var mat = new MaterialAnimEntry(matanim.Name);
mat.TexPatternMatAnim = matanim;
Materials.Add(mat);
foreach (PatternAnimInfo SamplerInfo in matanim.PatternAnimInfos)
{
BfresSamplerAnim sampler = new BfresSamplerAnim(SamplerInfo.Name, this);
mat.Samplers.Add(sampler);
int textureIndex = 0;
if (SamplerInfo.SubBindIndex != -1)
{
textureIndex = SamplerInfo.SubBindIndex;
var group = new Animation.KeyGroup();
group.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = textureIndex });
group.Constant = true;
sampler.group = group;
}
if (SamplerInfo.CurveIndex != -1)
{
int index = (int)SamplerInfo.CurveIndex;
Animation.KeyGroup keyGroup = CurveHelper.CreateTrackWiiU(matanim.Curves[index]);
keyGroup.AnimDataOffset = matanim.Curves[index].AnimDataOffset;
sampler.group = new KeyGroup()
{
AnimDataOffset = keyGroup.AnimDataOffset,
Keys = keyGroup.Keys,
};
foreach (var ind in keyGroup.Keys)
{
Console.WriteLine($"{SamplerInfo.Name} {ind.Value}");
}
}
}
}
}
public class MaterialAnimEntry : Material
{
public TexPatternMatAnim TexPatternMatAnim;
public MaterialAnimEntry(string name) : base(name)
{
}
public void LoadMaterial(TexPatternMatAnim data)
{
TexPatternMatAnim = data;
}
public TexPatternMatAnim SaveData()
{
TexPatternMatAnim.Name = Text;
return TexPatternMatAnim;
}
}
public class BfresSamplerAnim : Material.Sampler
{
FTXP AnimWrapper;
public BfresSamplerAnim(string Name, FTXP ftxp)
{
Text = Name;
ImageKey = "texture";
SelectedImageKey = "texture";
AnimWrapper = ftxp;
}
public override string GetActiveTextureName(int frame)
{
uint val = (uint)group.GetValue(frame);
return AnimWrapper.Textures[(int)val];
}
public override STGenericTexture GetActiveTexture(int frame)
{
uint val = (uint)group.GetValue(frame);
foreach (var ftexFolder in PluginRuntime.ftexContainers)
{
try
{
string name = GetActiveTextureName(frame);
if (ftexFolder.ResourceNodes.ContainsKey(name))
return (STGenericTexture)ftexFolder.ResourceNodes[name];
}
catch
{
throw new Exception("Index out of range " + val);
}
}
return null;
}
}
public override void NextFrame(Viewport viewport)
{
//Loop through each drawable bfres in the active viewport to display the anim
foreach (var drawable in viewport.scene.objects)
{
if (drawable is BFRESRender)
LoadMaterialAnimation(((BFRESRender)drawable).models);
}
}
private void LoadMaterialAnimation(List<FMDL> models)
{
//Loop through each FMDL's materials until it matches the material anim
foreach (var model in models)
{
foreach (Material matAnim in Materials)
{
if (model.materials.ContainsKey(matAnim.Text))
SetTextureAnimation(model.materials[matAnim.Text], matAnim);
}
}
}
private void SetTextureAnimation(FMAT material, Material matAnim)
{
if (matAnim.Samplers.Count == 0)
return;
//Loop through sampler list for texture anims
//These store a list of indices (step curve) to grab a texture name list
//Then we'll update the active texture
foreach (Material.Sampler samplerAnim in matAnim.Samplers)
{
foreach (MatTexture texture in material.TextureMaps)
{
if (texture.SamplerName == samplerAnim.Text)
{
texture.textureState = STGenericMatTexture.TextureState.Animated;
uint index = (uint)samplerAnim.group.GetValue(Frame);
texture.animatedTexName = Textures[(int)index];
}
}
}
}
public override string ExportFilter => FileFilters.GetFilter(typeof(FTXP));
public override void Export(string FileName)
{
TexPatternAnim.Export(FileName, GetResFile());
}
public override void Replace(string FileName) {
Replace(FileName, GetResFile());
}
public void Replace(string FileName, ResFile resFile)
{
string ext = Utils.GetExtension(FileName);
if (ext == ".bftxp")
{
TexPatternAnim.Import(FileName, resFile);
TexPatternAnim.Name = Text;
LoadAnim(TexPatternAnim);
}
else if (ext == ".gif")
{
BFRESGroupNode ftexFolder = PluginRuntime.ftexContainers[0];
GifToTexturePatternAnimation anim = new GifToTexturePatternAnimation(FileName, ftexFolder, this);
TexPatternAnim.Name = Text;
LoadAnim(TexPatternAnim);
}
}
}
}

View file

@ -0,0 +1,250 @@
using System;
using System.Collections.Generic;
using Switch_Toolbox.Library;
using System.Windows.Forms;
using FirstPlugin;
using Syroot.NintenTools.NSW.Bfres;
using FirstPlugin.Forms;
using Switch_Toolbox.Library.Animations;
using ResU = Syroot.NintenTools.Bfres;
namespace Bfres.Structs
{
public class FVIS : VisibilityAnimation
{
public VisibilityAnim VisibilityAnim;
public ResU.VisibilityAnim VisibilityAnimU;
public FVIS()
{
ImageKey = "visibilityAnim";
SelectedImageKey = "visibilityAnim";
}
public ResFile GetResFile() {
return ((BFRESGroupNode)Parent).GetResFile();
}
public ResU.ResFile GetResFileU() {
return ((BFRESGroupNode)Parent).GetResFileU();
}
public override void OnClick(TreeView treeView) => UpdateEditor();
public void UpdateEditor(){
((BFRES)Parent.Parent.Parent).LoadEditors(this);
}
public override string ExportFilter => FileFilters.GetFilter(typeof(FVIS));
public override void Export(string FileName)
{
VisibilityAnim.Export(FileName, GetResFile());
}
public override void Replace(string FileName)
{
Replace(FileName, GetResFile(), GetResFileU());
}
public void Replace(string FileName, ResFile resFileNX, ResU.ResFile resFileU)
{
if (resFileNX != null)
{
VisibilityAnim.Import(FileName);
VisibilityAnim.Name = Text;
}
else
{
VisibilityAnimU.Import(FileName, resFileU);
VisibilityAnimU.Name = Text;
}
}
public void SaveData()
{
if (!IsEdited) //Use original data instead of generic data from editors
return;
if (VisibilityAnimU != null)
{
VisibilityAnimU.Name = Text;
VisibilityAnimU.Names = BoneNames;
VisibilityAnimU.Path = "";
}
else
{
VisibilityAnim.Name = Text;
VisibilityAnim.Names = BoneNames;
VisibilityAnim.Path = "";
VisibilityAnim.FrameCount = FrameCount;
VisibilityAnim.BaseDataList = new bool[BoneNames.Count];
int boneIndex = 0;
foreach (BooleanKeyGroup value in Values)
{
if (!value.Constant)
{
AnimCurve curve = new AnimCurve();
curve.AnimDataOffset = (uint)BoneNames.IndexOf(value.Text);
curve.Scale = value.Scale;
curve.Offset = value.Offset;
curve.KeyType = AnimCurveKeyType.SByte;
curve.FrameType = CurveHelper.GetFrameType((uint)FrameCount);
curve.CurveType = AnimCurveType.StepBool;
if (IsBaked)
curve.CurveType = AnimCurveType.BakedBool;
curve.Delta = value.Delta;
curve.EndFrame = value.EndFrame;
curve.StartFrame = value.StartFrame;
List<bool> KeyBooleans = new List<bool>();
List<float> KeyFrames = new List<float>();
for (int frame = 0; frame < value.Keys.Count; frame++)
{
bool currentValue = value.Keys[frame].Visible;
float currentFrame = value.Keys[frame].Frame;
if (frame > 0)
{
bool previousValue = value.Keys[frame - 1].Visible;
if (previousValue != currentValue)
{
KeyFrames.Add(currentFrame);
KeyBooleans.Add(currentValue);
}
}
else
{
KeyFrames.Add(currentFrame);
KeyBooleans.Add(currentValue);
VisibilityAnim.BaseDataList[boneIndex] = currentValue;
}
}
curve.KeyStepBoolData = KeyBooleans.ToArray();
for (int frame = 0; frame < FrameCount; frame++)
{
}
}
else
{
//Else for constant types it's only base values
}
boneIndex++;
}
}
}
public FVIS(ResU.VisibilityAnim anim) { LoadAnim(anim); }
public FVIS(VisibilityAnim anim) { LoadAnim(anim); }
private void LoadAnim(ResU.VisibilityAnim vis)
{
VisibilityAnimU = vis;
FrameCount = vis.FrameCount;
Text = vis.Name;
if (vis.BaseDataList == null)
vis.BaseDataList = new bool[0];
if (vis.Names == null)
vis.Names = new string[0];
BaseValues = vis.BaseDataList;
foreach (var name in vis.Names)
BoneNames.Add(name);
for (int curve = 0; curve < vis.Curves.Count; curve++)
{
Values.Add(CurveHelper.CreateBooleanTrackWiiU(vis.Curves[curve]));
}
}
private void LoadAnim(VisibilityAnim vis)
{
VisibilityAnim = vis;
FrameCount = vis.FrameCount;
Text = vis.Name;
if (vis.BaseDataList == null)
vis.BaseDataList = new bool[0];
if (vis.Names == null)
vis.Names = new string[0];
BaseValues = vis.BaseDataList;
foreach (var name in vis.Names)
BoneNames.Add(name);
for (int curve = 0; curve < vis.Curves.Count; curve++)
{
var track = CurveHelper.CreateBooleanTrack(vis.Curves[curve]);
track.Text = BoneNames[(int)track.AnimDataOffset];
Values.Add(track);
}
}
public override void NextFrame(Viewport viewport)
{
if (viewport.scene == null)
return;
//Loop through each drawable bfres in the active viewport to display the anim
foreach (var drawable in viewport.scene.objects)
{
if (drawable is BFRESRender)
HideBones(((BFRESRender)drawable).models);
}
}
private void HideBones(List<FMDL> models)
{
foreach (var model in models)
{
if (Frame == 0)
{
foreach (var bone in model.Skeleton.bones)
bone.Visible = true;
//Hide base values
int index = 0;
foreach (var baseVal in BaseValues)
{
string boneName = BoneNames[index++];
foreach (var bone in model.Skeleton.bones)
if (bone.Text == boneName)
bone.Visible = baseVal;
}
}
//Hide values for each curve
foreach (var group in Values)
{
string boneName = group.Text;
foreach (var bone in model.Skeleton.bones)
{
if (bone.Text == boneName)
{
bone.Visible = group.GetValue(Frame);
Console.WriteLine($"{Frame} {bone.Text} {bone.Visible}");
}
}
}
}
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL;
namespace FirstPlugin
{
public class GLEnumConverter
{
}
}

View file

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Syroot.NintenTools.NSW.Bfres;
using Bfres.Structs;
namespace FirstPlugin
{
public class KsaShader
{
public static void LoadRenderInfo(FMAT mat, List<BfresRenderInfo> renderInfos)
{
foreach (var renderInfo in renderInfos)
{
switch (renderInfo.Name)
{
case "renderPass":
mat.isTransparent = renderInfo.ValueString[0] == "xlu";
break;
}
}
}
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FirstPlugin
{
public enum AglCullFace
{
Front,
Back,
Both
}
public enum AglRenderState
{
Front,
Back,
Both
}
}

View file

@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using ByamlExt.Byaml;
using ByamlExt;
using FirstPlugin.Turbo;
namespace FirstPlugin
{
public class BYAML : IEditor<ByamlEditor>, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "BYAML" };
public string[] Extension { get; set; } = new string[] { "*.byaml", "*.byml", "*.bprm", "*.sbyml" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
if (reader.CheckSignature(2, "BY") || reader.CheckSignature(2, "YB"))
return true;
else
return false;
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
class EditableNode
{
public Type type { get => Node[Index].GetType(); }
dynamic Node;
dynamic Index;
public dynamic Get() => Node[Index];
public void Set(dynamic value) => Node[Index] = value;
public string GetTreeViewString()
{
if (Index is int)
return Node[Index].ToString();
else
return Index + " : " + Node[Index].ToString();
}
public EditableNode(dynamic _node, dynamic _index)
{
Node = _node;
Index = _index;
}
}
bool IsDialog = false;
BymlFileData data;
public ByamlEditor OpenForm()
{
ByamlEditor editor = new ByamlEditor(data.RootNode, data.SupportPaths, data.Version, data.byteOrder, IsDialog, FileName);
editor.FileFormat = this;
editor.Text = FileName;
editor.Dock = DockStyle.Fill;
return editor;
}
public void Load(Stream stream)
{
CanSave = true;
IsDialog = IFileInfo != null && IFileInfo.InArchive;
Console.WriteLine($"IsDialog " + IsDialog);
data = ByamlFile.LoadN(stream, false);
}
public void Unload()
{
}
public byte[] Save()
{
MemoryStream mem = new MemoryStream();
ByamlFile.SaveN(mem, new BymlFileData
{
Version = data.Version,
byteOrder = data.byteOrder,
SupportPaths = data.SupportPaths,
RootNode = data.RootNode
});
return mem.ToArray();
}
}
}

View file

@ -0,0 +1,821 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using GL_EditorFramework.Interfaces;
using OpenTK.Graphics.OpenGL;
using OpenTK;
using Switch_Toolbox.Library.Rendering;
using GL_EditorFramework.GL_Core;
using System.Drawing;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library.Forms;
using GL_EditorFramework.EditorDrawables;
namespace FirstPlugin
{
public class KCL : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "KCL" };
public string[] Extension { get; set; } = new string[] { "*.kcl" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
return reader.ReadUInt32() == 0x02020000;
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
types.Add(typeof(MenuExt));
return types.ToArray();
}
}
byte[] data;
STToolStripItem EndiannessToolstrip;
public KCL()
{
ContextMenuStrip = new STContextMenuStrip();
ContextMenuStrip.Items.Add(new STToolStripItem("Save", Save));
ContextMenuStrip.Items.Add(new STToolStripItem("Export", Export));
ContextMenuStrip.Items.Add(new STToolStripItem("Replace", Replace));
EndiannessToolstrip = new STToolStripItem("Big Endian Mode", SwapEndianess) { Checked = true };
ContextMenuStrip.Items.Add(EndiannessToolstrip);
CanSave = true;
IFileInfo = new IFileInfo();
}
public void Load(System.IO.Stream stream)
{
Text = FileName;
Renderer = new KCLRendering();
stream.Position = 0;
data = stream.ToArray();
Read(data);
}
class MenuExt : IFileMenuExtension
{
public STToolStripItem[] NewFileMenuExtensions => null;
public STToolStripItem[] NewFromFileMenuExtensions => newFileExt;
public STToolStripItem[] ToolsMenuExtensions => null;
public STToolStripItem[] TitleBarExtensions => null;
public STToolStripItem[] CompressionMenuExtensions => null;
public STToolStripItem[] ExperimentalMenuExtensions => null;
STToolStripItem[] newFileExt = new STToolStripItem[2];
public MenuExt()
{
newFileExt[0] = new STToolStripItem("KCL (Switch)", CreateNew);
newFileExt[1] = new STToolStripItem("KCL (Wii U)", CreateNew);
}
public void CreateNew(object sender, EventArgs args)
{
var ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
if (sender.ToString() == "KCL (Wii U)")
ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
OpenFileDialog opn = new OpenFileDialog();
if (opn.ShowDialog() != DialogResult.OK) return;
var mod = EditorCore.Common.OBJ.Read(new MemoryStream(File.ReadAllBytes(opn.FileName)), null);
string name = Path.GetFileNameWithoutExtension(opn.FileName);
var f = MarioKart.MK7.KCL.FromOBJ(mod);
KCL kcl = new KCL();
kcl.Text = name;
kcl.IFileInfo = new IFileInfo();
kcl.FileName = name;
kcl.Renderer = new KCLRendering();
kcl.Read(f.Write(ByteOrder));
ObjectEditor editor = new ObjectEditor();
editor.Text = name;
editor.treeViewCustom1.Nodes.Add(kcl);
LibraryGUI.Instance.CreateMdiWindow(editor);
}
}
public void Unload()
{
}
public byte[] Save()
{
return data;
}
public enum GameSet : ushort
{
MarioOdyssey = 0x0,
MarioKart8D = 0x1,
Splatoon2 = 0x2,
}
public enum CollisionType_MarioOdssey : ushort
{
}
public enum CollisionType_MK8D : ushort
{
Road_Default = 0,
Road_Bumpy = 2,
Road_Sand = 4,
Offroad_Sand = 6,
Road_HeavySand = 8,
Road_IcyRoad = 9,
OrangeBooster = 10,
AntiGravityPanel = 11,
Latiku = 16,
Wall5 = 17,
Wall4 = 19,
Wall = 23,
Latiku2 = 28,
Glider = 31,
SidewalkSlope = 32,
Road_Dirt = 33,
Unsolid = 56,
Water = 60,
Road_Stone = 64,
Wall1 = 81,
Wall2 = 84,
FinishLine = 93,
RedFlowerEffect = 95,
Wall3 = 113,
WhiteFlowerEffect = 127,
Road_Metal = 128,
Road_3DS_MP_Piano = 129,
Road_RoyalR_Grass = 134,
TopPillar = 135,
YoshiCuiruit_Grass = 144,
YellowFlowerEffect = 159,
Road_MetalGating = 160,
Road_3DS_MP_Xylophone = 161,
Road_3DS_MP_Vibraphone = 193,
SNES_RR_road = 227,
Offroad_Mud = 230,
Trick = 4096,
BoosterStunt = 4106,
TrickEndOfRamp = 4108,
Trick3 = 4130,
Trick6 = 4160,
Trick4 = 4224,
Trick5 = 8192,
BoostTrick = 8202,
}
public void Save(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Supported Formats|*.kcl";
sfd.FileName = Text;
sfd.DefaultExt = ".kcl";
if (sfd.ShowDialog() == DialogResult.OK)
{
STFileSaver.SaveFileFormat(this, sfd.FileName);
}
}
private Syroot.BinaryData.ByteOrder endianness;
public Syroot.BinaryData.ByteOrder Endianness
{
get
{
return endianness;
}
set
{
endianness = value;
if (value == Syroot.BinaryData.ByteOrder.BigEndian)
EndiannessToolstrip.Checked = true;
else
EndiannessToolstrip.Checked = false;
}
}
public void Export(object sender, EventArgs args)
{
if (kcl == null)
return;
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Supported Formats|*.obj";
sfd.FileName = Text;
sfd.DefaultExt = ".obj";
if (sfd.ShowDialog() == DialogResult.OK)
{
kcl.ToOBJ().toWritableObj().WriteObj(sfd.FileName + ".obj");
}
}
public void Replace(object sender, EventArgs args)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Supported Formats|*.obj";
if (ofd.ShowDialog() == DialogResult.OK)
{
var mod = EditorCore.Common.OBJ.Read(new MemoryStream(File.ReadAllBytes(ofd.FileName)), null);
if (mod.Faces.Count > 65535)
{
MessageBox.Show("this model has too many faces, only models with less than 65535 triangles can be converted");
return;
}
kcl = MarioKart.MK7.KCL.FromOBJ(mod);
data = kcl.Write(Endianness);
Read(data);
}
}
public void SwapEndianess(object sender, EventArgs args)
{
if (EndiannessToolstrip.Checked)
{
EndiannessToolstrip.Checked = false;
Endianness = Syroot.BinaryData.ByteOrder.LittleEndian;
}
else
{
EndiannessToolstrip.Checked = true;
Endianness = Syroot.BinaryData.ByteOrder.BigEndian;
}
}
KCLRendering Renderer;
bool IsLoaded = false;
public override void OnClick(TreeView treeView)
{
if (!Runtime.DisableViewport)
{
Viewport editor = (Viewport)LibraryGUI.Instance.GetActiveContent(typeof(Viewport));
if (editor == null)
{
editor = new Viewport();
LibraryGUI.Instance.LoadEditor(editor);
}
editor.Text = Text;
editor.Dock = DockStyle.Fill;
if (!IsLoaded)
{
editor.AddDrawable(Renderer);
editor.LoadObjects();
}
IsLoaded = true;
}
}
public MarioKart.MK7.KCL kcl = null;
public void Read(byte[] file_data)
{
try
{
Endianness = Syroot.BinaryData.ByteOrder.LittleEndian;
kcl = new MarioKart.MK7.KCL(file_data, Syroot.BinaryData.ByteOrder.LittleEndian);
}
catch
{
Endianness = Syroot.BinaryData.ByteOrder.BigEndian;
kcl = new MarioKart.MK7.KCL(file_data, Syroot.BinaryData.ByteOrder.BigEndian);
}
Read(kcl);
}
public void Read(MarioKart.MK7.KCL kcl)
{
Nodes.Clear();
Renderer.models.Clear();
int CurModelIndx = 0;
foreach (MarioKart.MK7.KCL.KCLModel mdl in kcl.Models)
{
KCLModel kclmodel = new KCLModel();
kclmodel.Text = "Model " + CurModelIndx;
int ft = 0;
foreach (var plane in mdl.Planes)
{
var triangle = mdl.GetTriangle(plane);
var normal = triangle.Normal;
var pointA = triangle.PointA;
var pointB = triangle.PointB;
var pointC = triangle.PointC;
Vertex vtx = new Vertex();
Vertex vtx2 = new Vertex();
Vertex vtx3 = new Vertex();
vtx.pos = new Vector3(Vec3D_To_Vec3(pointA));
vtx2.pos = new Vector3(Vec3D_To_Vec3(pointB));
vtx3.pos = new Vector3(Vec3D_To_Vec3(pointC));
vtx.nrm = new Vector3(Vec3D_To_Vec3(normal));
vtx2.nrm = new Vector3(Vec3D_To_Vec3(normal));
vtx3.nrm = new Vector3(Vec3D_To_Vec3(normal));
KCLModel.Face face = new KCLModel.Face();
face.Text = triangle.Collision.ToString();
face.MaterialFlag = triangle.Collision;
var col = MarioKart.MK7.KCLColors.GetMaterialColor(plane.CollisionType);
Vector3 ColorSet = new Vector3(col.R, col.G, col.B);
vtx.col = new Vector4(ColorSet, 1);
vtx2.col = new Vector4(ColorSet, 1);
vtx3.col = new Vector4(ColorSet, 1);
kclmodel.faces.Add(ft);
kclmodel.faces.Add(ft + 1);
kclmodel.faces.Add(ft + 2);
ft += 3;
kclmodel.vertices.Add(vtx);
kclmodel.vertices.Add(vtx2);
kclmodel.vertices.Add(vtx3);
}
Renderer.models.Add(kclmodel);
Nodes.Add(kclmodel);
CurModelIndx++;
}
}
public class KCLRendering : EditableObject
{
public Vector3 Position = new Vector3(0, 0, 0);
protected bool Selected = false;
protected bool Hovered = false;
public override bool IsSelected() => Selected;
public bool IsHovered() => Selected;
// gl buffer objects
int vbo_position;
int ibo_elements;
//Set the game's material list
public GameSet GameMaterialSet = GameSet.MarioKart8D;
public List<KCLModel> models = new List<KCLModel>();
private void GenerateBuffers()
{
GL.GenBuffers(1, out vbo_position);
GL.GenBuffers(1, out ibo_elements);
}
public void Destroy()
{
GL.DeleteBuffer(vbo_position);
GL.DeleteBuffer(ibo_elements);
}
public void UpdateVertexData()
{
if (!Runtime.OpenTKInitialized)
return;
DisplayVertex[] Vertices;
int[] Faces;
int poffset = 0;
int voffset = 0;
List<DisplayVertex> Vs = new List<DisplayVertex>();
List<int> Ds = new List<int>();
foreach (KCLModel m in models)
{
m.Offset = poffset * 4;
List<DisplayVertex> pv = m.CreateDisplayVertices();
Vs.AddRange(pv);
for (int i = 0; i < m.displayFaceSize; i++)
{
Ds.Add(m.display[i] + voffset);
}
poffset += m.displayFaceSize;
voffset += pv.Count;
}
// Binds
Vertices = Vs.ToArray();
Faces = Ds.ToArray();
// Bind only once!
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
GL.BufferData<DisplayVertex>(BufferTarget.ArrayBuffer, (IntPtr)(Vertices.Length * DisplayVertex.Size), Vertices, BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
GL.BufferData<int>(BufferTarget.ElementArrayBuffer, (IntPtr)(Faces.Length * sizeof(int)), Faces, BufferUsageHint.StaticDraw);
LibraryGUI.Instance.UpdateViewport();
}
public ShaderProgram defaultShaderProgram;
public ShaderProgram solidColorShaderProgram;
public override void Prepare(GL_ControlModern control)
{
string pathFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader") + "\\KCL.frag";
string pathVert = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader") + "\\KCL.vert";
var defaultFrag = new FragmentShader(File.ReadAllText(pathFrag));
var defaultVert = new VertexShader(File.ReadAllText(pathVert));
var solidColorFrag = new FragmentShader(
@"#version 330
uniform vec4 color;
void main(){
gl_FragColor = color;
}");
var solidColorVert = new VertexShader(
@"#version 330
in vec3 vPosition;
in vec3 vNormal;
in vec3 vColor;
out vec3 normal;
out vec3 color;
out vec3 position;
uniform mat4 mtxMdl;
uniform mat4 mtxCam;
void main(){
normal = vNormal;
color = vColor;
position = vPosition;
gl_Position = mtxMdl * mtxCam * vec4(vPosition.xyz, 1.0);
}");
defaultShaderProgram = new ShaderProgram(defaultFrag, defaultVert);
solidColorShaderProgram = new ShaderProgram(solidColorFrag, solidColorVert);
}
public override void Prepare(GL_ControlLegacy control)
{
string pathFrag = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Legacy") + "\\KCL.frag";
string pathVert = System.IO.Path.Combine(Runtime.ExecutableDir, "Shader", "Legacy") + "\\KCL.vert";
var defaultFrag = new FragmentShader(File.ReadAllText(pathFrag));
var defaultVert = new VertexShader(File.ReadAllText(pathVert));
var solidColorFrag = new FragmentShader(
@"#version 330
uniform vec4 color;
void main(){
gl_FragColor = color;
}");
var solidColorVert = new VertexShader(
@"#version 330
in vec3 vPosition;
in vec3 vNormal;
in vec3 vColor;
out vec3 normal;
out vec3 color;
out vec3 position;
void main(){
normal = vNormal;
color = vColor;
position = vPosition;
gl_Position = mvpMatrix * vec4(vPosition.xyz, 1.0);
}");
defaultShaderProgram = new ShaderProgram(defaultFrag, defaultVert);
solidColorShaderProgram = new ShaderProgram(solidColorFrag, solidColorVert);
}
private void CheckBuffers()
{
if (!Runtime.OpenTKInitialized)
return;
bool buffersWereInitialized = ibo_elements != 0 && vbo_position != 0;
if (!buffersWereInitialized)
{
GenerateBuffers();
UpdateVertexData();
}
}
public override void Draw(GL_ControlLegacy control, Pass pass)
{
CheckBuffers();
if (!Runtime.OpenTKInitialized)
return;
}
public override void Draw(GL_ControlModern control, Pass pass)
{
}
public override void Draw(GL_ControlModern control, Pass pass, EditorScene editorScene)
{
CheckBuffers();
if (!Runtime.OpenTKInitialized)
return;
control.CurrentShader = defaultShaderProgram;
defaultShaderProgram.EnableVertexAttributes();
SetRenderSettings(defaultShaderProgram);
Matrix4 previewScale = Utils.TransformValues(Vector3.Zero, Vector3.Zero, Runtime.previewScale);
Matrix4 camMat = previewScale * control.mtxCam * control.mtxProj;
GL.Disable(EnableCap.CullFace);
GL.Uniform3(defaultShaderProgram["difLightDirection"], Vector3.TransformNormal(new Vector3(0f, 0f, -1f), camMat.Inverted()).Normalized());
GL.Uniform3(defaultShaderProgram["difLightColor"], new Vector3(1));
GL.Uniform3(defaultShaderProgram["ambLightColor"], new Vector3(1));
defaultShaderProgram.EnableVertexAttributes();
SetRenderSettings(defaultShaderProgram);
foreach (KCLModel mdl in models)
{
DrawModel(mdl, defaultShaderProgram);
}
defaultShaderProgram.DisableVertexAttributes();
GL.UseProgram(0);
GL.Disable(EnableCap.DepthTest);
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.CullFace);
}
private void SetRenderSettings(ShaderProgram shader)
{
shader.SetBoolToInt("renderVertColor", Runtime.renderVertColor);
GL.Uniform1(defaultShaderProgram["renderType"], (int)Runtime.viewportShading);
}
private void DrawModel(KCLModel m, ShaderProgram shader, bool drawSelection = false)
{
if (m.faces.Count <= 3)
return;
SetVertexAttributes(m, shader);
if (m.Checked)
{
if ((m.IsSelected))
{
DrawModelSelection(m, shader);
}
else
{
if (Runtime.RenderModelWireframe)
{
DrawModelWireframe(m, shader);
}
if (Runtime.RenderModels)
{
GL.DrawElements(PrimitiveType.Triangles, m.displayFaceSize, DrawElementsType.UnsignedInt, m.Offset);
}
}
}
}
private static void DrawModelSelection(KCLModel p, ShaderProgram shader)
{
//This part needs to be reworked for proper outline. Currently would make model disappear
GL.DrawElements(PrimitiveType.Triangles, p.displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
GL.Enable(EnableCap.StencilTest);
// use vertex color for wireframe color
GL.Uniform1(shader["colorOverride"], 1);
GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
GL.Enable(EnableCap.LineSmooth);
GL.LineWidth(1.5f);
GL.DrawElements(PrimitiveType.Triangles, p.displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
GL.Uniform1(shader["colorOverride"], 0);
GL.Enable(EnableCap.DepthTest);
}
private void SetVertexAttributes(KCLModel m, ShaderProgram shader)
{
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
GL.VertexAttribPointer(shader.GetAttribute("vPosition"), 3, VertexAttribPointerType.Float, false, DisplayVertex.Size, 0);
GL.VertexAttribPointer(shader.GetAttribute("vNormal"), 3, VertexAttribPointerType.Float, false, DisplayVertex.Size, 12);
GL.VertexAttribPointer(shader.GetAttribute("vColor"), 3, VertexAttribPointerType.Float, false, DisplayVertex.Size, 24);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
}
private static void DrawModelWireframe(KCLModel p, ShaderProgram shader)
{
// use vertex color for wireframe color
GL.Uniform1(shader["colorOverride"], 1);
GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
GL.Enable(EnableCap.LineSmooth);
GL.LineWidth(1.5f);
GL.DrawElements(PrimitiveType.Triangles, p.displayFaceSize, DrawElementsType.UnsignedInt, p.Offset);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
GL.Uniform1(shader["colorOverride"], 0);
}
public override void ApplyTransformationToSelection(DeltaTransform deltaTransform)
{
Position += deltaTransform.Translation;
}
public override bool CanStartDragging() => true;
public override Vector3 GetSelectionCenter()
{
return Position;
}
public override uint Select(int index, I3DControl control)
{
Selected = true;
control.AttachPickingRedrawer();
return 0;
}
public override uint SelectDefault(I3DControl control)
{
Selected = true;
control.AttachPickingRedrawer();
return 0;
}
public override uint SelectAll(I3DControl control)
{
Selected = true;
control.AttachPickingRedrawer();
return 0;
}
public override uint Deselect(int index, I3DControl control)
{
Selected = false;
control.DetachPickingRedrawer();
return 0;
}
public override uint DeselectAll(I3DControl control)
{
Selected = false;
control.DetachPickingRedrawer();
return 0;
}
}
//Convert KCL lib vec3 to opentk one so i can use the cross and dot methods
public static Vector3 Vec3D_To_Vec3(System.Windows.Media.Media3D.Vector3D v)
{
return new Vector3((float)v.X, (float)v.Y, (float)v.Z);
}
public struct DisplayVertex
{
// Used for rendering.
public Vector3 pos;
public Vector3 nrm;
public Vector3 col;
public static int Size = 4 * (3 + 3 + 3);
}
public class KCLModel : STGenericObject
{
public KCLModel()
{
ImageKey = "mesh";
SelectedImageKey = "mesh";
Checked = true;
}
public int[] display;
public int Offset; // For Rendering
public int strip = 0x40;
public int displayFaceSize = 0;
public class Face : TreeNode
{
public int MaterialFlag = 0;
}
public List<DisplayVertex> CreateDisplayVertices()
{
// rearrange faces
display = getDisplayFace().ToArray();
List<DisplayVertex> displayVertList = new List<DisplayVertex>();
if (faces.Count <= 3)
return displayVertList;
foreach (Vertex v in vertices)
{
DisplayVertex displayVert = new DisplayVertex()
{
pos = v.pos,
nrm = v.nrm,
col = v.col.Xyz,
};
displayVertList.Add(displayVert);
}
return displayVertList;
}
public List<int> getDisplayFace()
{
if ((strip >> 4) == 4)
{
displayFaceSize = faces.Count;
return faces;
}
else
{
List<int> f = new List<int>();
int startDirection = 1;
int p = 0;
int f1 = faces[p++];
int f2 = faces[p++];
int faceDirection = startDirection;
int f3;
do
{
f3 = faces[p++];
if (f3 == 0xFFFF)
{
f1 = faces[p++];
f2 = faces[p++];
faceDirection = startDirection;
}
else
{
faceDirection *= -1;
if ((f1 != f2) && (f2 != f3) && (f3 != f1))
{
if (faceDirection > 0)
{
f.Add(f3);
f.Add(f2);
f.Add(f1);
}
else
{
f.Add(f2);
f.Add(f3);
f.Add(f1);
}
}
f1 = f2;
f2 = f3;
}
} while (p < faces.Count);
displayFaceSize = f.Count;
return f;
}
}
}
}
}

View file

@ -0,0 +1,344 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox.Library;
using Switch_Toolbox.Library.Rendering;
using System.Windows.Forms;
using OpenTK;
namespace FirstPlugin
{
public class CsvModel : IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "CSV Model" };
public string[] Extension { get; set; } = new string[] { "*.csv" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
return false;
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public List<STGenericObject> objects = new List<STGenericObject>();
public class Model
{
public string Name { get; set; }
public int UVChannelCount { get; set; }
public DataType type;
public DataSubType subType;
public List<string[]> bones = new List<string[]>();
public List<float[]> weights = new List<float[]>();
}
public enum DataType : int
{
vertex = 1,
faces = 2,
bones = 3,
}
public enum DataSubType : int
{
position = 0,
normals = 1,
colors = 2,
uv0 = 3,
uv1 = 4,
uv2 = 5,
uv3 = 6,
}
float X, Y, Z, W;
public void Load(System.IO.Stream stream)
{
LoadFile(stream);
}
public void LoadFile(Stream stream, bool IsModel = false)
{
if (!IsModel)
{
MessageBox.Show("Not valid model csv");
return;
}
string line = null;
List<Model> models = new List<Model>();
TextReader csv = new StreamReader(stream);
Model model = new Model();
STGenericObject STobj = new STGenericObject();
Vertex vtx = new Vertex();
STGenericObject.LOD_Mesh lod = new STGenericObject.LOD_Mesh();
int Index = 0;
int ww = 0;
while (true)
{
line = csv.ReadLine();
if (line != null)
{
if (line.StartsWith("Obj Name"))
{
model = new Model();
STobj = new STGenericObject();
model.Name = line.Split(':')[1].Replace("\n", "");
model.subType = DataSubType.position;
models.Add(model);
STobj.ObjectName = model.Name;
lod = new STGenericObject.LOD_Mesh();
lod.IndexFormat = STIndexFormat.UInt16;
lod.PrimitiveType = STPolygonType.Triangle;
STobj.lodMeshes.Add(lod);
STobj.VertexBufferIndex = Index;
objects.Add(STobj);
Index++;
}
else if (line.StartsWith("tex_Array:"))
{
}
else if (line.StartsWith("Bone_Suport"))
{
}
else if (line.StartsWith("Color_Suport"))
{
}
else if (line.StartsWith("UV_Num:"))
{
int uvCount;
int.TryParse(line.Split(':')[1].Replace("\n", ""), out uvCount);
model.UVChannelCount = uvCount;
}
else if (line.StartsWith("vert_Array"))
{
model.type = DataType.vertex;
}
else if (line.StartsWith("face_Array"))
{
model.type = DataType.faces;
}
else if (line.StartsWith("bone_Array"))
{
model.type = DataType.bones;
}
else
{
string[] values = line.Replace("\n", "").Replace("\r", "").Split(',');
if (model.type == DataType.vertex)
{
switch (model.subType)
{
case DataSubType.position:
vtx = new Vertex();
STobj.vertices.Add(vtx);
STobj.HasPos = true;
float.TryParse(values[0], out X);
float.TryParse(values[1], out Y);
float.TryParse(values[2], out Z);
vtx.pos = new Vector3(X, Y, Z);
model.subType = DataSubType.normals;
break;
case DataSubType.normals:
STobj.HasNrm = true;
float.TryParse(values[0], out X);
float.TryParse(values[1], out Y);
float.TryParse(values[2], out Z);
vtx.nrm = new Vector3(X, Y, Z);
model.subType = DataSubType.colors;
break;
case DataSubType.colors:
STobj.HasVertColors = true;
float.TryParse(values[0], out X);
float.TryParse(values[1], out Y);
float.TryParse(values[2], out Z);
float.TryParse(values[3], out W);
vtx.col = new Vector4(X / 255, Y / 255, Z / 255, 1);
model.subType = DataSubType.uv0;
break;
case DataSubType.uv0:
STobj.HasUv0 = true;
float.TryParse(values[0], out X);
float.TryParse(values[1], out Y);
vtx.uv0 = new Vector2(X, 1 - Y);
if (model.UVChannelCount == 1)
model.subType = DataSubType.position;
else
model.subType = DataSubType.uv1;
break;
case DataSubType.uv1:
STobj.HasUv1 = true;
float.TryParse(values[0], out X);
float.TryParse(values[1], out Y);
vtx.uv1 = new Vector2(X, 1 - Y);
if (model.UVChannelCount == 2)
model.subType = DataSubType.position;
else
model.subType = DataSubType.uv2;
break;
case DataSubType.uv2:
STobj.HasUv2 = true;
float.TryParse(values[0], out X);
float.TryParse(values[1], out Y);
vtx.uv2 = new Vector2(X, 1 - Y);
if (model.UVChannelCount == 3)
model.subType = DataSubType.position;
else
model.subType = DataSubType.uv3;
break;
case DataSubType.uv3:
float.TryParse(values[0], out X);
float.TryParse(values[1], out Y);
model.subType = DataSubType.position;
break;
}
}
if (model.type == DataType.faces)
{
int face;
foreach (string v in values)
{
var cleaned = v.Replace(".0", string.Empty);
int.TryParse(cleaned, out face);
lod.faces.Add(face-1);
}
}
if (model.type == DataType.bones)
{
STobj.HasWeights = true;
STobj.HasIndices = true;
Array.Resize(ref values, values.Length - 1);
List<string> bones = new List<string>();
List<float> weights = new List<float>();
int bbs = 0;
foreach (string obj in values)
{
if (bbs == 0)
{
bones.Add(obj);
bbs += 1;
}
else
{
float.TryParse(obj, out X);
weights.Add(X);
bbs = 0;
}
}
STobj.bones.Add(bones.ToArray());
STobj.weightsT.Add(weights.ToArray());
}
}
}
else
break;
}
if (objects[0].weightsT.Count != objects[0].vertices.Count)
throw new Exception("Incorrect vertex amount");
foreach (STGenericObject obj in objects)
{
obj.lodMeshes[0].GenerateSubMesh();
for (int v = 0; v < obj.vertices.Count; v++)
{
foreach (string bn in obj.bones[v])
obj.vertices[v].boneNames.Add(bn);
foreach (float f in obj.weightsT[v])
obj.vertices[v].boneWeights.Add(f);
}
foreach (Vertex v in obj.vertices)
{
if (v.boneNames.Count == 1)
Console.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]}");
if (v.boneNames.Count == 2)
Console.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]}");
if (v.boneNames.Count == 3)
Console.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]}");
if (v.boneNames.Count == 4)
Console.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]} {v.boneNames[3]} {v.boneWeights[3]}");
}
}
csv.Close();
csv = null;
}
public void Unload()
{
}
public byte[] Save()
{
MemoryStream mem = new MemoryStream();
using (System.IO.StreamWriter file = new System.IO.StreamWriter(mem))
{
foreach (STGenericObject obj in objects)
{
file.WriteLine($"Obj Name:" + obj.ObjectName);
file.WriteLine($"Bone_Suport");
file.WriteLine($"UV_Num:1");
file.WriteLine($"vert_Array");
foreach (Vertex v in obj.vertices)
{
file.WriteLine($"{v.pos.X},{v.pos.Y},{v.pos.Z}");
file.WriteLine($"{v.nrm.X},{v.nrm.Y},{v.nrm.Z}");
file.WriteLine($"{v.col.X * 255},{v.col.Y * 255},{v.col.Z * 255},{v.col.W * 255}");
file.WriteLine($"{v.uv0.X},{v.uv0.Y}");
// file.WriteLine($"{v.uv1.X},{v.uv1.Y}");
}
file.WriteLine($"face_Array");
for (int f = 0; f < obj.faces.Count / 3; f++)
{
file.WriteLine($"{obj.faces[f] + 1},{obj.faces[f++] + 1},{obj.faces[f++] + 1}");
}
file.WriteLine($"bone_Array");
foreach (Vertex v in obj.vertices)
{
if (v.boneNames.Count == 1)
file.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]}");
if (v.boneNames.Count == 2)
file.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]}");
if (v.boneNames.Count == 3)
file.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]}");
if (v.boneNames.Count == 4)
file.WriteLine($"{v.boneNames[0]} {v.boneWeights[0]} {v.boneNames[1]} {v.boneWeights[1]} {v.boneNames[2]} {v.boneWeights[2]} {v.boneNames[3]} {v.boneWeights[3]}");
}
}
file.Close();
}
return mem.ToArray();
}
}
}

View file

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox.Library.IO;
using Switch_Toolbox.Library;
namespace FirstPlugin
{
public class EFF : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Namco Effect" };
public string[] Extension { get; set; } = new string[] { "*.eff" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "EFFN");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public void Load(System.IO.Stream stream)
{
Text = FileName;
FileReader reader = new FileReader(stream);
reader.Seek(4096, System.IO.SeekOrigin.Begin);
PTCL pctl = new PTCL();
pctl.Text = "Output.pctl";
Nodes.Add(pctl);
PTCL.Header Header = new PTCL.Header();
Header.Read(reader, pctl);
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,213 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
using System.IO;
using Switch_Toolbox.Library.IO;
namespace FirstPlugin
{
public class BFFNT : TreeNodeFile, IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Cafe Font" };
public string[] Extension { get; set; } = new string[] { "*.bffnt" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(Stream stream)
{
using (var reader = new FileReader(stream, true))
{
return reader.CheckSignature(4, "FFNT");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public void Load(System.IO.Stream stream)
{
FFNT bffnt = new FFNT();
bffnt.Read(new FileReader(stream));
TGLP tglp = bffnt.finf.tglp;
int i = 0;
foreach (byte[] texture in tglp.SheetDataList)
{
SheetEntry sheet = new SheetEntry();
sheet.data = texture;
sheet.Text = "Sheet" + i++;
}
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
public class SheetEntry : TreeNodeCustom
{
public SheetEntry()
{
ImageKey = "fileBlank";
SelectedImageKey = "fileBlank";
ContextMenu = new ContextMenu();
MenuItem export = new MenuItem("Export");
ContextMenu.MenuItems.Add(export);
export.Click += Export;
}
public byte[] data;
public override void OnClick(TreeView treeview)
{
}
private void Export(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.FileName = Text;
sfd.DefaultExt = "bntx";
sfd.Filter = "Supported Formats|*.bntx;|" +
"All files(*.*)|*.*";
if (sfd.ShowDialog() == DialogResult.OK)
{
File.WriteAllBytes(sfd.FileName, data);
}
}
}
}
public class FFNT
{
public ushort BOM;
public uint Version;
public FINF finf;
public void Read(FileReader reader)
{
string Signature = reader.ReadString(4, Encoding.ASCII);
if (Signature != "FFNT")
throw new Exception($"Invalid signature {Signature}! Expected FFNT.");
char[] Magic = reader.ReadChars(4);
BOM = reader.ReadUInt16();
Version = reader.ReadUInt32();
uint FileSize = reader.ReadUInt16();
uint BlockCount = reader.ReadUInt16();
uint unk = reader.ReadUInt16();
finf = new FINF();
finf.Read(reader);
reader.Close();
reader.Dispose();
}
}
public class FINF
{
public uint Size;
public uint Type;
public uint Width;
public uint Height;
public uint Ascend;
public uint LineFeed;
public uint AlterCharIndex;
public uint DefaultLeftWidth;
public uint DefaultGlyphWidth;
public uint DefaultCharWidth;
public uint CharEncoding;
public TGLP tglp;
public void Read(FileReader reader)
{
string Signature = reader.ReadString(4, Encoding.ASCII);
if (Signature != "FINF")
throw new Exception($"Invalid signature {Signature}! Expected FINF.");
Size = reader.ReadUInt32();
Type = reader.ReadByte();
Height = reader.ReadByte();
Width = reader.ReadByte();
Ascend = reader.ReadByte();
LineFeed = reader.ReadUInt16();
AlterCharIndex = reader.ReadUInt16();
DefaultLeftWidth = reader.ReadByte();
DefaultGlyphWidth = reader.ReadByte();
DefaultCharWidth = reader.ReadByte();
CharEncoding = reader.ReadByte();
uint tglpOffset = reader.ReadUInt32();
uint cwdhOffset = reader.ReadUInt32();
uint cmapOffset = reader.ReadUInt32();
tglp = new TGLP();
using (reader.TemporarySeek(tglpOffset - 8, SeekOrigin.Begin))
{
tglp.Read(reader);
}
}
}
public class TGLP
{
public uint Size;
public uint CellWidth;
public uint CellHeight;
public uint MaxCharWidth;
public uint SheetSize;
public uint BaseLinePos;
public uint Format;
public uint ColumnCount;
public uint RowCount;
public uint SheetWidth;
public uint SheetHeight;
public List<byte[]> SheetDataList = new List<byte[]>();
public void Read(FileReader reader)
{
string Signature = reader.ReadString(4, Encoding.ASCII);
if (Signature != "TGLP")
throw new Exception($"Invalid signature {Signature}! Expected TGLP.");
Size = reader.ReadUInt32();
CellWidth = reader.ReadByte();
CellHeight = reader.ReadByte();
byte SheetCount = reader.ReadByte();
MaxCharWidth = reader.ReadByte();
SheetSize = reader.ReadUInt32();
BaseLinePos = reader.ReadUInt16();
Format = reader.ReadUInt16();
ColumnCount = reader.ReadUInt16();
RowCount = reader.ReadUInt16();
SheetWidth = reader.ReadUInt16();
SheetHeight = reader.ReadUInt16();
uint sheetOffset = reader.ReadUInt32();
using (reader.TemporarySeek(sheetOffset, SeekOrigin.Begin))
{
for (int i = 0; i < SheetCount; i++)
{
}
SheetDataList.Add(reader.ReadBytes((int)SheetSize * SheetCount));
}
}
}
}

View file

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
namespace FirstPlugin
{
public class BFLAN : IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Cafe Layout Animation (GUI)" };
public string[] Extension { get; set; } = new string[] { "*.bflan" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "FLAN");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public void Load(System.IO.Stream stream)
{
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
}
}

View file

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Switch_Toolbox;
using System.Windows.Forms;
using Switch_Toolbox.Library;
namespace FirstPlugin
{
public class BFLYT : IFileFormat
{
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Cafe Layout (GUI)" };
public string[] Extension { get; set; } = new string[] { "*.bflyt" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new Switch_Toolbox.Library.IO.FileReader(stream, true))
{
return reader.CheckSignature(4, "FLYT");
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public void Load(System.IO.Stream stream)
{
}
public void Unload()
{
}
public byte[] Save()
{
return null;
}
}
}

Some files were not shown because too many files have changed in this diff Show more