Repository: xivapi/SaintCoinach
Branch: master
Commit: 0b22b78f9795
Files: 1641
Total size: 2.3 MB
Directory structure:
gitextract_w62xzu50/
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── RELEASE.md
│ └── workflows/
│ ├── build.yml
│ └── json-validation.yaml
├── .gitignore
├── DotSquish/
│ ├── Alpha.cs
│ ├── ClusterFit.cs
│ ├── ColourBlock.cs
│ ├── ColourFit.cs
│ ├── ColourSet.cs
│ ├── DotSquish.csproj
│ ├── Flags.cs
│ ├── Maths.cs
│ └── Squish.cs
├── Godbert/
│ ├── App.config
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── Commands/
│ │ └── DelegateCommand.cs
│ ├── Controls/
│ │ ├── AttachedImage.cs
│ │ ├── ColumnFactory.cs
│ │ ├── INavigatable.cs
│ │ ├── IRawDataColumn.cs
│ │ ├── RawDataGrid.cs
│ │ ├── RawDataGridColorColumn.cs
│ │ ├── RawDataGridImageColumn.cs
│ │ ├── RawDataGridKeyColumn.cs
│ │ ├── RawDataGridTextColumn.cs
│ │ └── RawDataItemsSource.cs
│ ├── EngineHelper.cs
│ ├── EngineInstance.cs
│ ├── Godbert.csproj
│ ├── MainWindow.xaml
│ ├── MainWindow.xaml.cs
│ ├── Models/
│ │ ├── ModelCharaHierarchy.cs
│ │ ├── ModelCharaMain.cs
│ │ ├── ModelCharaSub.cs
│ │ └── ModelCharaVariant.cs
│ ├── NaturalComparer.cs
│ ├── ObservableBase.cs
│ ├── Properties/
│ │ ├── AssemblyInfo.cs
│ │ ├── Resources.Designer.cs
│ │ ├── Resources.resx
│ │ ├── Settings.Designer.cs
│ │ └── Settings.settings
│ ├── Settings.cs
│ ├── ViewModels/
│ │ ├── BookmarkViewModel.cs
│ │ ├── DataViewModel.cs
│ │ ├── DemihumanViewModel.cs
│ │ ├── EquipmentViewModel.cs
│ │ ├── FurnitureViewModel.cs
│ │ ├── MainViewModel.cs
│ │ ├── MapsViewModel.cs
│ │ ├── MonstersViewModel.cs
│ │ └── TerritoryViewModel.cs
│ ├── Views/
│ │ ├── DataView.xaml
│ │ ├── DataView.xaml.cs
│ │ ├── DemihumansView.xaml
│ │ ├── DemihumansView.xaml.cs
│ │ ├── EquipmentView.xaml
│ │ ├── EquipmentView.xaml.cs
│ │ ├── FurnitureView.xaml
│ │ ├── FurnitureView.xaml.cs
│ │ ├── Help3DView.xaml
│ │ ├── Help3DView.xaml.cs
│ │ ├── MapsView.xaml
│ │ ├── MapsView.xaml.cs
│ │ ├── MonstersView.xaml
│ │ ├── MonstersView.xaml.cs
│ │ ├── TerritoryView.xaml
│ │ └── TerritoryView.xaml.cs
│ └── WpfHelper.cs
├── LICENSE
├── NewAdditionsByPatch.txt
├── README.md
├── SaintCoinach/
│ ├── ARealmReversed.cs
│ ├── ByteArrayExtensions.cs
│ ├── Definitions/
│ │ ├── AOZArrangement.json
│ │ ├── AOZBoss.json
│ │ ├── AOZContent.json
│ │ ├── AOZContentBriefingBNpc.json
│ │ ├── AOZContentBriefingObject.json
│ │ ├── AOZReport.json
│ │ ├── AOZScore.json
│ │ ├── Achievement.json
│ │ ├── AchievementCategory.json
│ │ ├── AchievementHideCondition.json
│ │ ├── AchievementKind.json
│ │ ├── AchievementTarget.json
│ │ ├── Action.json
│ │ ├── ActionCastTimeline.json
│ │ ├── ActionCastVFX.json
│ │ ├── ActionCategory.json
│ │ ├── ActionComboRoute.json
│ │ ├── ActionIndirection.json
│ │ ├── ActionParam.json
│ │ ├── ActionProcStatus.json
│ │ ├── ActionTimeline.json
│ │ ├── ActionTimelineMove.json
│ │ ├── ActionTimelineReplace.json
│ │ ├── ActionTransient.json
│ │ ├── ActivityFeedButtons.json
│ │ ├── ActivityFeedCaptions.json
│ │ ├── ActivityFeedGroupCaptions.json
│ │ ├── ActivityFeedImages.json
│ │ ├── Addon.json
│ │ ├── Adventure.json
│ │ ├── AdventureExPhase.json
│ │ ├── AetherCurrent.json
│ │ ├── AetherCurrentCompFlgSet.json
│ │ ├── AetherialWheel.json
│ │ ├── Aetheryte.json
│ │ ├── AetheryteSystemDefine.json
│ │ ├── AetheryteTransient.json
│ │ ├── AirshipExplorationLevel.json
│ │ ├── AirshipExplorationLog.json
│ │ ├── AirshipExplorationParamType.json
│ │ ├── AirshipExplorationPart.json
│ │ ├── AirshipExplorationPoint.json
│ │ ├── AkatsukiNote.json
│ │ ├── AkatsukiNoteString.json
│ │ ├── AnimaWeapon5.json
│ │ ├── AnimaWeapon5Param.json
│ │ ├── AnimaWeapon5PatternGroup.json
│ │ ├── AnimaWeapon5SpiritTalk.json
│ │ ├── AnimaWeapon5SpiritTalkParam.json
│ │ ├── AnimaWeapon5TradeItem.json
│ │ ├── AnimaWeaponFUITalk.json
│ │ ├── AnimaWeaponFUITalkParam.json
│ │ ├── AnimaWeaponIcon.json
│ │ ├── AnimaWeaponItem.json
│ │ ├── AnimationLOD.json
│ │ ├── AozAction.json
│ │ ├── AozActionTransient.json
│ │ ├── AquariumFish.json
│ │ ├── AquariumWater.json
│ │ ├── ArchiveItem.json
│ │ ├── ArrayEventHandler.json
│ │ ├── AttackType.json
│ │ ├── Attract.json
│ │ ├── BGM.json
│ │ ├── BGMFade.json
│ │ ├── BGMFadeType.json
│ │ ├── BGMScene.json
│ │ ├── BGMSituation.json
│ │ ├── BGMSwitch.json
│ │ ├── BGMSystemDefine.json
│ │ ├── BNpcAnnounceIcon.json
│ │ ├── BNpcBase.json
│ │ ├── BNpcBasePopVfx.json
│ │ ├── BNpcCustomize.json
│ │ ├── BNpcName.json
│ │ ├── BNpcParts.json
│ │ ├── BNpcState.json
│ │ ├── BacklightColor.json
│ │ ├── Ballista.json
│ │ ├── Balloon.json
│ │ ├── BannerBg.json
│ │ ├── BannerCondition.json
│ │ ├── BannerDecoration.json
│ │ ├── BannerDesignPreset.json
│ │ ├── BannerFacial.json
│ │ ├── BannerFrame.json
│ │ ├── BannerObtainHintType.json
│ │ ├── BannerPreset.json
│ │ ├── BannerTimeline.json
│ │ ├── BaseParam.json
│ │ ├── BattleLeve.json
│ │ ├── BattleLeveRule.json
│ │ ├── BeastRankBonus.json
│ │ ├── BeastReputationRank.json
│ │ ├── BeastTribe.json
│ │ ├── Behavior.json
│ │ ├── BehaviorPath.json
│ │ ├── BenchmarkOverrideEquipment.json
│ │ ├── Booster.json
│ │ ├── Buddy.json
│ │ ├── BuddyAction.json
│ │ ├── BuddyEquip.json
│ │ ├── BuddyItem.json
│ │ ├── BuddyRank.json
│ │ ├── BuddySkill.json
│ │ ├── CSBonusContent.json
│ │ ├── CSBonusContentIdentifier.json
│ │ ├── CSBonusContentType.json
│ │ ├── CSBonusMission.json
│ │ ├── CSBonusMissionType.json
│ │ ├── CSBonusSeason.json
│ │ ├── CSBonusTextData.json
│ │ ├── Cabinet.json
│ │ ├── CabinetCategory.json
│ │ ├── Calendar.json
│ │ ├── Carry.json
│ │ ├── Channeling.json
│ │ ├── CharaCardBase.json
│ │ ├── CharaCardDecoration.json
│ │ ├── CharaCardDesignCategory.json
│ │ ├── CharaCardDesignPreset.json
│ │ ├── CharaCardDesignType.json
│ │ ├── CharaCardHeader.json
│ │ ├── CharaCardPlayStyle.json
│ │ ├── CharaMakeClassEquip.json
│ │ ├── CharaMakeCustomize.json
│ │ ├── CharaMakeName.json
│ │ ├── CharaMakeType.json
│ │ ├── ChocoboRace.json
│ │ ├── ChocoboRaceAbility.json
│ │ ├── ChocoboRaceAbilityType.json
│ │ ├── ChocoboRaceItem.json
│ │ ├── ChocoboRaceRank.json
│ │ ├── ChocoboRaceStatus.json
│ │ ├── ChocoboRaceTerritory.json
│ │ ├── ChocoboRaceTutorial.json
│ │ ├── ChocoboRaceWeather.json
│ │ ├── ChocoboTaxi.json
│ │ ├── ChocoboTaxiStand.json
│ │ ├── CircleActivity.json
│ │ ├── ClassJob.json
│ │ ├── ClassJobActionSort.json
│ │ ├── ClassJobCategory.json
│ │ ├── CollectablesShop.json
│ │ ├── CollectablesShopItem.json
│ │ ├── CollectablesShopItemGroup.json
│ │ ├── CollectablesShopRefine.json
│ │ ├── CollectablesShopRewardItem.json
│ │ ├── CollectablesShopRewardScrip.json
│ │ ├── Companion.json
│ │ ├── CompanionMove.json
│ │ ├── CompanionTransient.json
│ │ ├── CompanyAction.json
│ │ ├── CompanyCraftDraft.json
│ │ ├── CompanyCraftDraftCategory.json
│ │ ├── CompanyCraftManufactoryState.json
│ │ ├── CompanyCraftPart.json
│ │ ├── CompanyCraftProcess.json
│ │ ├── CompanyCraftSequence.json
│ │ ├── CompanyCraftSupplyItem.json
│ │ ├── CompanyCraftType.json
│ │ ├── CompanyLeve.json
│ │ ├── CompanyLeveRule.json
│ │ ├── CompleteJournal.json
│ │ ├── CompleteJournalCategory.json
│ │ ├── Completion.json
│ │ ├── Condition.json
│ │ ├── ConfigKey.json
│ │ ├── ContentCloseCycle.json
│ │ ├── ContentEventItem.json
│ │ ├── ContentExAction.json
│ │ ├── ContentFinderCondition.json
│ │ ├── ContentFinderConditionTransient.json
│ │ ├── ContentGauge.json
│ │ ├── ContentGaugeColor.json
│ │ ├── ContentMemberType.json
│ │ ├── ContentNpc.json
│ │ ├── ContentNpcTalk.json
│ │ ├── ContentRandomSelect.json
│ │ ├── ContentRoulette.json
│ │ ├── ContentRouletteOpenRule.json
│ │ ├── ContentRouletteRoleBonus.json
│ │ ├── ContentTalk.json
│ │ ├── ContentTalkParam.json
│ │ ├── ContentType.json
│ │ ├── ContentsNote.json
│ │ ├── ContentsTutorial.json
│ │ ├── ContentsTutorialPage.json
│ │ ├── CraftAction.json
│ │ ├── CraftLeve.json
│ │ ├── CraftLeveTalk.json
│ │ ├── CraftLevelDifference.json
│ │ ├── CraftType.json
│ │ ├── Credit.json
│ │ ├── CreditBackImage.json
│ │ ├── CreditCast.json
│ │ ├── CreditList.json
│ │ ├── CreditListText.json
│ │ ├── CustomTalk.json
│ │ ├── CustomTalkDefineClient.json
│ │ ├── CustomTalkNestHandlers.json
│ │ ├── CutSceneIncompQuest.json
│ │ ├── CutScreenImage.json
│ │ ├── Cutscene.json
│ │ ├── CutsceneMotion.json
│ │ ├── CutsceneWorkIndex.json
│ │ ├── CycleTime.json
│ │ ├── DailySupplyItem.json
│ │ ├── DawnContent.json
│ │ ├── DawnContentParticipable.json
│ │ ├── DawnGrowMember.json
│ │ ├── DawnMember.json
│ │ ├── DawnMemberUIParam.json
│ │ ├── DawnQuestMember.json
│ │ ├── DeepDungeon.json
│ │ ├── DeepDungeonBan.json
│ │ ├── DeepDungeonDanger.json
│ │ ├── DeepDungeonDemiclone.json
│ │ ├── DeepDungeonEquipment.json
│ │ ├── DeepDungeonFloorEffectUI.json
│ │ ├── DeepDungeonItem.json
│ │ ├── DeepDungeonLayer.json
│ │ ├── DeepDungeonMagicStone.json
│ │ ├── DeepDungeonMap5X.json
│ │ ├── DeepDungeonRoom.json
│ │ ├── DeepDungeonStatus.json
│ │ ├── DefaultTalk.json
│ │ ├── DefaultTalkLipSyncType.json
│ │ ├── DeliveryQuest.json
│ │ ├── Description.json
│ │ ├── DescriptionPage.json
│ │ ├── DescriptionSection.json
│ │ ├── DescriptionString.json
│ │ ├── DisposalShop.json
│ │ ├── DisposalShopFilterType.json
│ │ ├── DisposalShopItem.json
│ │ ├── DpsChallenge.json
│ │ ├── DpsChallengeOfficer.json
│ │ ├── DpsChallengeTransient.json
│ │ ├── DynamicEvent.json
│ │ ├── DynamicEventEnemyType.json
│ │ ├── DynamicEventSingleBattle.json
│ │ ├── DynamicEventType.json
│ │ ├── ENpcBase.json
│ │ ├── ENpcDressUp.json
│ │ ├── ENpcDressUpDress.json
│ │ ├── ENpcResident.json
│ │ ├── EObj.json
│ │ ├── EObjName.json
│ │ ├── EmjAddon.json
│ │ ├── EmjDani.json
│ │ ├── Emote.json
│ │ ├── EmoteCategory.json
│ │ ├── EmoteMode.json
│ │ ├── EquipRaceCategory.json
│ │ ├── EquipSlotCategory.json
│ │ ├── EurekaAetherItem.json
│ │ ├── EurekaAethernet.json
│ │ ├── EurekaDungeonPortal.json
│ │ ├── EurekaGrowData.json
│ │ ├── EurekaLogosMixerProbability.json
│ │ ├── EurekaMagiaAction.json
│ │ ├── EurekaMagiciteItem.json
│ │ ├── EurekaMagiciteItemType.json
│ │ ├── EurekaSphereElementAdjust.json
│ │ ├── EventAction.json
│ │ ├── EventCustomIconType.json
│ │ ├── EventIconPriority.json
│ │ ├── EventIconPriorityPair.json
│ │ ├── EventIconType.json
│ │ ├── EventItem.json
│ │ ├── EventItemCastTimeline.json
│ │ ├── EventItemHelp.json
│ │ ├── EventItemTimeline.json
│ │ ├── EventPathMove.json
│ │ ├── EventSystemDefine.json
│ │ ├── ExVersion.json
│ │ ├── ExportedGatheringPoint.json
│ │ ├── ExportedSG.json
│ │ ├── ExtraCommand.json
│ │ ├── FCActivity.json
│ │ ├── FCActivityCategory.json
│ │ ├── FCAuthority.json
│ │ ├── FCAuthorityCategory.json
│ │ ├── FCChestName.json
│ │ ├── FCCrestSymbol.json
│ │ ├── FCHierarchy.json
│ │ ├── FCProfile.json
│ │ ├── FCRank.json
│ │ ├── FCReputation.json
│ │ ├── FCRights.json
│ │ ├── FGSAddon.json
│ │ ├── FGSStageUI.json
│ │ ├── FashionCheckThemeCategory.json
│ │ ├── FashionCheckWeeklyTheme.json
│ │ ├── Fate.json
│ │ ├── FateEvent.json
│ │ ├── FateMode.json
│ │ ├── FateProgressUI.json
│ │ ├── FateShop.json
│ │ ├── FateTokenType.json
│ │ ├── FccShop.json
│ │ ├── Festival.json
│ │ ├── FieldMarker.json
│ │ ├── FishParameter.json
│ │ ├── FishingBaitParameter.json
│ │ ├── FishingNoteInfo.json
│ │ ├── FishingRecordType.json
│ │ ├── FishingRecordTypeTransient.json
│ │ ├── FishingSpot.json
│ │ ├── FittingShop.json
│ │ ├── FittingShopCategory.json
│ │ ├── FittingShopCategoryItem.json
│ │ ├── FittingShopItemSet.json
│ │ ├── Frontline03.json
│ │ ├── FurnitureCatalogCategory.json
│ │ ├── FurnitureCatalogItemList.json
│ │ ├── GCRankGridaniaFemaleText.json
│ │ ├── GCRankGridaniaMaleText.json
│ │ ├── GCRankLimsaFemaleText.json
│ │ ├── GCRankLimsaMaleText.json
│ │ ├── GCRankUldahFemaleText.json
│ │ ├── GCRankUldahMaleText.json
│ │ ├── GCScripShopCategory.json
│ │ ├── GCScripShopItem.json
│ │ ├── GCShop.json
│ │ ├── GCShopItemCategory.json
│ │ ├── GCSupplyDuty.json
│ │ ├── GCSupplyDutyReward.json
│ │ ├── GFATE.json
│ │ ├── GFateClimbing2.json
│ │ ├── GFateClimbing2Content.json
│ │ ├── GFateClimbing2TotemType.json
│ │ ├── GFateRideShooting.json
│ │ ├── GFateType.json
│ │ ├── GameRewardObtainType.json
│ │ ├── GardeningSeed.json
│ │ ├── GathererCrafterTool.json
│ │ ├── GathererReductionReward.json
│ │ ├── GatheringCondition.json
│ │ ├── GatheringExp.json
│ │ ├── GatheringItem.json
│ │ ├── GatheringItemLevelConvertTable.json
│ │ ├── GatheringItemPoint.json
│ │ ├── GatheringLeve.json
│ │ ├── GatheringLeveRoute.json
│ │ ├── GatheringLeveRule.json
│ │ ├── GatheringNotebookList.json
│ │ ├── GatheringPoint.json
│ │ ├── GatheringPointBase.json
│ │ ├── GatheringPointBonus.json
│ │ ├── GatheringPointBonusType.json
│ │ ├── GatheringPointName.json
│ │ ├── GatheringPointTransient.json
│ │ ├── GatheringRarePopTimeTable.json
│ │ ├── GatheringSubCategory.json
│ │ ├── GatheringType.json
│ │ ├── GcArmyCaptureTactics.json
│ │ ├── GcArmyEquipPreset.json
│ │ ├── GcArmyExpedition.json
│ │ ├── GcArmyExpeditionMemberBonus.json
│ │ ├── GcArmyExpeditionType.json
│ │ ├── GcArmyMemberGrow.json
│ │ ├── GcArmyTraining.json
│ │ ├── GeneralAction.json
│ │ ├── GilShop.json
│ │ ├── GilShopItem.json
│ │ ├── GimmickAccessor.json
│ │ ├── GimmickJump.json
│ │ ├── GimmickRect.json
│ │ ├── Glasses.json
│ │ ├── GlassesStyle.json
│ │ ├── GoldSaucerArcadeMachine.json
│ │ ├── GoldSaucerTextData.json
│ │ ├── GrandCompany.json
│ │ ├── GrandCompanyRank.json
│ │ ├── GroupPoseFrame.json
│ │ ├── GroupPoseStamp.json
│ │ ├── GroupPoseStampCategory.json
│ │ ├── GuardianDeity.json
│ │ ├── Guide.json
│ │ ├── GuidePage.json
│ │ ├── GuidePageString.json
│ │ ├── GuideTitle.json
│ │ ├── GuildOrder.json
│ │ ├── GuildOrderGuide.json
│ │ ├── GuildOrderOfficer.json
│ │ ├── GuildleveAssignment.json
│ │ ├── GuildleveAssignmentCategory.json
│ │ ├── GuildleveAssignmentTalk.json
│ │ ├── HWDAnnounce.json
│ │ ├── HWDCrafterSupply.json
│ │ ├── HWDCrafterSupplyReward.json
│ │ ├── HWDCrafterSupplyTerm.json
│ │ ├── HWDDevLayerControl.json
│ │ ├── HWDDevLevelUI.json
│ │ ├── HWDDevLively.json
│ │ ├── HWDDevProgress.json
│ │ ├── HWDGathereInspectTerm.json
│ │ ├── HWDGathererInspection.json
│ │ ├── HWDGathererInspectionReward.json
│ │ ├── HWDInfoBoardArticle.json
│ │ ├── HWDInfoBoardArticleTransient.json
│ │ ├── HWDInfoBoardArticleType.json
│ │ ├── HWDLevelChangeDeception.json
│ │ ├── HWDSharedGroup.json
│ │ ├── HWDSharedGroupControlParam.json
│ │ ├── HairMakeType.json
│ │ ├── HouseRetainerPose.json
│ │ ├── HousingAethernet.json
│ │ ├── HousingAppeal.json
│ │ ├── HousingEmploymentNpcList.json
│ │ ├── HousingEmploymentNpcRace.json
│ │ ├── HousingExterior.json
│ │ ├── HousingFurniture.json
│ │ ├── HousingLandSet.json
│ │ ├── HousingMapMarkerInfo.json
│ │ ├── HousingMerchantPose.json
│ │ ├── HousingPlacement.json
│ │ ├── HousingPreset.json
│ │ ├── HousingUnitedExterior.json
│ │ ├── HousingYardObject.json
│ │ ├── HowTo.json
│ │ ├── HowToCategory.json
│ │ ├── HowToPage.json
│ │ ├── HugeCraftworksNpc.json
│ │ ├── HugeCraftworksRank.json
│ │ ├── IKDContentBonus.json
│ │ ├── IKDFishParam.json
│ │ ├── IKDRoute.json
│ │ ├── IKDRouteTable.json
│ │ ├── IKDSpot.json
│ │ ├── IconLanguage.json
│ │ ├── InclusionShop.json
│ │ ├── InclusionShopCategory.json
│ │ ├── InclusionShopSeries.json
│ │ ├── InclusionShopWelcom.json
│ │ ├── InclusionShopWelcomText.json
│ │ ├── IndividualWeather.json
│ │ ├── InstanceContent.json
│ │ ├── InstanceContentBuff.json
│ │ ├── InstanceContentGuide.json
│ │ ├── InstanceContentQICData.json
│ │ ├── InstanceContentTextData.json
│ │ ├── Item.json
│ │ ├── ItemAction.json
│ │ ├── ItemActionTelepo.json
│ │ ├── ItemBarterCheck.json
│ │ ├── ItemFood.json
│ │ ├── ItemLevel.json
│ │ ├── ItemRepairPrice.json
│ │ ├── ItemRepairResource.json
│ │ ├── ItemRetainerLevelUp.json
│ │ ├── ItemSearchCategory.json
│ │ ├── ItemSeries.json
│ │ ├── ItemSortCategory.json
│ │ ├── ItemSpecialBonus.json
│ │ ├── ItemStainCondition.json
│ │ ├── ItemUICategory.json
│ │ ├── Jingle.json
│ │ ├── JobHudManual.json
│ │ ├── JobHudManualPriority.json
│ │ ├── JournalCategory.json
│ │ ├── JournalGenre.json
│ │ ├── JournalSection.json
│ │ ├── KineDriverOffGroup.json
│ │ ├── Knockback.json
│ │ ├── LegacyQuest.json
│ │ ├── Leve.json
│ │ ├── LeveAssignmentType.json
│ │ ├── LeveClient.json
│ │ ├── LeveRewardItem.json
│ │ ├── LeveRewardItemGroup.json
│ │ ├── LeveString.json
│ │ ├── LeveVfx.json
│ │ ├── Level.json
│ │ ├── Lobby.json
│ │ ├── LogFilter.json
│ │ ├── LogKind.json
│ │ ├── LogMessage.json
│ │ ├── LotteryExchangeShop.json
│ │ ├── MJIAnimals.json
│ │ ├── MJIBuilding.json
│ │ ├── MJIBuildingPlace.json
│ │ ├── MJICraftworksObject.json
│ │ ├── MJICraftworksObjectTheme.json
│ │ ├── MJICraftworksPopularity.json
│ │ ├── MJICraftworksPopularityType.json
│ │ ├── MJICraftworksRankRatio.json
│ │ ├── MJICraftworksSupplyDefine.json
│ │ ├── MJICraftworksTension.json
│ │ ├── MJICropSeed.json
│ │ ├── MJIDisposalShopItem.json
│ │ ├── MJIDisposalShopUICategory.json
│ │ ├── MJIFarmPastureRank.json
│ │ ├── MJIFunction.json
│ │ ├── MJIGardenscaping.json
│ │ ├── MJIGathering.json
│ │ ├── MJIGatheringItem.json
│ │ ├── MJIGatheringObject.json
│ │ ├── MJIGatheringTool.json
│ │ ├── MJIHudMode.json
│ │ ├── MJIItemCategory.json
│ │ ├── MJIItemPouch.json
│ │ ├── MJIKeyItem.json
│ │ ├── MJILandmark.json
│ │ ├── MJILandmarkPlace.json
│ │ ├── MJILivelyActor.json
│ │ ├── MJIMinionPopAreas.json
│ │ ├── MJIName.json
│ │ ├── MJINekomimiRequest.json
│ │ ├── MJIProgress.json
│ │ ├── MJIRank.json
│ │ ├── MJIRecipe.json
│ │ ├── MJIRecipeMaterial.json
│ │ ├── MJIStockyardManagementArea.json
│ │ ├── MJIStockyardManagementTable.json
│ │ ├── MJIText.json
│ │ ├── MJIVillageAppearanceSG.json
│ │ ├── MJIVillageAppearanceUI.json
│ │ ├── MJIVillageDevelopment.json
│ │ ├── MKDLore.json
│ │ ├── MYCTemporaryItem.json
│ │ ├── MYCTemporaryItemUICategory.json
│ │ ├── MYCWarResultNotebook.json
│ │ ├── MacroIcon.json
│ │ ├── MacroIconRedirectOld.json
│ │ ├── MainCommand.json
│ │ ├── MainCommandCategory.json
│ │ ├── MandervilleWeaponEnhance.json
│ │ ├── ManeuversArmor.json
│ │ ├── Map.json
│ │ ├── MapCondition.json
│ │ ├── MapExclusive.json
│ │ ├── MapMarker.json
│ │ ├── MapMarkerRegion.json
│ │ ├── MapReplace.json
│ │ ├── MapSymbol.json
│ │ ├── MapTransientPvPMap.json
│ │ ├── MapType.json
│ │ ├── Marker.json
│ │ ├── Materia.json
│ │ ├── MateriaGrade.json
│ │ ├── MateriaJoinRate.json
│ │ ├── MateriaJoinRateGatherCraft.json
│ │ ├── McGuffin.json
│ │ ├── McGuffinUIData.json
│ │ ├── MiniGameRA.json
│ │ ├── MiniGameTurnBreakAction.json
│ │ ├── MiniGameTurnBreakConst.json
│ │ ├── MiniGameTurnBreakEnemy.json
│ │ ├── MiniGameTurnBreakPop.json
│ │ ├── MiniGameTurnBreakPopOffset.json
│ │ ├── MiniGameTurnBreakStage.json
│ │ ├── MiniGameTurnBreakStatus.json
│ │ ├── MinionRace.json
│ │ ├── MinionRules.json
│ │ ├── MinionSkillType.json
│ │ ├── MirageStoreSetItem.json
│ │ ├── MirageStoreSetItemLookup.json
│ │ ├── MobHuntOrder.json
│ │ ├── MobHuntOrderType.json
│ │ ├── MobHuntReward.json
│ │ ├── MobHuntRewardCap.json
│ │ ├── MobHuntTarget.json
│ │ ├── ModelChara.json
│ │ ├── ModelSkeleton.json
│ │ ├── ModelState.json
│ │ ├── MonsterNote.json
│ │ ├── MonsterNoteTarget.json
│ │ ├── MotionTimeline.json
│ │ ├── MotionTimelineBlendTable.json
│ │ ├── Mount.json
│ │ ├── MountAction.json
│ │ ├── MountCustomize.json
│ │ ├── MountFlyingCondition.json
│ │ ├── MountSpeed.json
│ │ ├── MountTransient.json
│ │ ├── MoveTimeline.json
│ │ ├── MoveVfx.json
│ │ ├── MovieStaffList.json
│ │ ├── MovieSubtitle.json
│ │ ├── MovieSubtitle500.json
│ │ ├── MovieSubtitleVoyage.json
│ │ ├── MultipleHelp.json
│ │ ├── MultipleHelpPage.json
│ │ ├── MultipleHelpString.json
│ │ ├── NotebookDivision.json
│ │ ├── NotebookDivisionCategory.json
│ │ ├── NotoriousMonster.json
│ │ ├── NotoriousMonsterTerritory.json
│ │ ├── NpcEquip.json
│ │ ├── NpcYell.json
│ │ ├── Omen.json
│ │ ├── Omikuji.json
│ │ ├── OmikujiGuidance.json
│ │ ├── OnlineStatus.json
│ │ ├── OpenContent.json
│ │ ├── OpenContentCandidateName.json
│ │ ├── Opening.json
│ │ ├── Orchestrion.json
│ │ ├── OrchestrionCategory.json
│ │ ├── OrchestrionPath.json
│ │ ├── OrchestrionUiparam.json
│ │ ├── Ornament.json
│ │ ├── OrnamentAction.json
│ │ ├── ParamGrow.json
│ │ ├── PartyContent.json
│ │ ├── PartyContentCutscene.json
│ │ ├── PartyContentTextData.json
│ │ ├── PatchMark.json
│ │ ├── Perform.json
│ │ ├── PerformGroup.json
│ │ ├── PerformTransient.json
│ │ ├── Pet.json
│ │ ├── PetAction.json
│ │ ├── PetMirage.json
│ │ ├── PhysicsGroup.json
│ │ ├── PhysicsWind.json
│ │ ├── Picture.json
│ │ ├── PlaceName.json
│ │ ├── PlantPotFlowerSeed.json
│ │ ├── PlayerSearchLocation.json
│ │ ├── PlayerSearchSubLocation.json
│ │ ├── PreHandler.json
│ │ ├── PresetCamera.json
│ │ ├── PresetCameraAdjust.json
│ │ ├── PreviewableItems.json
│ │ ├── PublicContent.json
│ │ ├── PublicContentCutscene.json
│ │ ├── PublicContentTextData.json
│ │ ├── PvPAction.json
│ │ ├── PvPActionSort.json
│ │ ├── PvPBaseParamValue.json
│ │ ├── PvPRank.json
│ │ ├── PvPSelectTrait.json
│ │ ├── PvPSeries.json
│ │ ├── PvPSeriesLevel.json
│ │ ├── PvPTrait.json
│ │ ├── Quest.json
│ │ ├── QuestAcceptAdditionCondition.json
│ │ ├── QuestBattle.json
│ │ ├── QuestChapter.json
│ │ ├── QuestClassJobReward.json
│ │ ├── QuestClassJobSupply.json
│ │ ├── QuestDefineClient.json
│ │ ├── QuestDerivedClass.json
│ │ ├── QuestEffect.json
│ │ ├── QuestEffectDefine.json
│ │ ├── QuestEventAreaEntranceInfo.json
│ │ ├── QuestLinkMarker.json
│ │ ├── QuestLinkMarkerIcon.json
│ │ ├── QuestLinkMarkerSet.json
│ │ ├── QuestRedo.json
│ │ ├── QuestRedoChapterUI.json
│ │ ├── QuestRedoChapterUICategory.json
│ │ ├── QuestRedoChapterUITab.json
│ │ ├── QuestRedoIncompChapter.json
│ │ ├── QuestRepeatFlag.json
│ │ ├── QuestRewardOther.json
│ │ ├── QuestSelectTitle.json
│ │ ├── QuestSetDefine.json
│ │ ├── QuickChat.json
│ │ ├── QuickChatTransient.json
│ │ ├── RPParameter.json
│ │ ├── Race.json
│ │ ├── RacingChocoboItem.json
│ │ ├── RacingChocoboName.json
│ │ ├── RacingChocoboNameCategory.json
│ │ ├── RacingChocoboNameInfo.json
│ │ ├── RacingChocoboParam.json
│ │ ├── RaidFinderParam.json
│ │ ├── ReactionEventObject.json
│ │ ├── ReactionEventObjectInfo.json
│ │ ├── RecastNavimesh.json
│ │ ├── Recipe.json
│ │ ├── RecipeLevelTable.json
│ │ ├── RecipeLookup.json
│ │ ├── RecipeNotebookList.json
│ │ ├── RecommendContents.json
│ │ ├── Relic.json
│ │ ├── Relic3.json
│ │ ├── RelicItem.json
│ │ ├── RelicNote.json
│ │ ├── RelicNoteCategory.json
│ │ ├── ReplaceAction.json
│ │ ├── Resident.json
│ │ ├── ResistanceWeaponAdjust.json
│ │ ├── RetainerFortuneRewardRange.json
│ │ ├── RetainerTask.json
│ │ ├── RetainerTaskLvRange.json
│ │ ├── RetainerTaskNormal.json
│ │ ├── RetainerTaskParameter.json
│ │ ├── RetainerTaskRandom.json
│ │ ├── RideShooting.json
│ │ ├── RideShootingTargetType.json
│ │ ├── RideShootingTextData.json
│ │ ├── SatisfactionArbitration.json
│ │ ├── SatisfactionBonusGuarantee.json
│ │ ├── SatisfactionNpc.json
│ │ ├── SatisfactionSupply.json
│ │ ├── SatisfactionSupplyReward.json
│ │ ├── ScenarioTree.json
│ │ ├── ScenarioTreeTips.json
│ │ ├── ScenarioTreeTipsClassQuest.json
│ │ ├── ScenarioType.json
│ │ ├── ScreenImage.json
│ │ ├── SecretRecipeBook.json
│ │ ├── SharlayanCraftWorks.json
│ │ ├── SharlayanCraftWorksSupply.json
│ │ ├── ShellFixedFromCommand.json
│ │ ├── SkyIsland2Mission.json
│ │ ├── SkyIsland2MissionDetail.json
│ │ ├── SkyIsland2MissionType.json
│ │ ├── SkyIsland2RangeType.json
│ │ ├── Snipe.json
│ │ ├── SnipeTalk.json
│ │ ├── SnipeTalkName.json
│ │ ├── SpearfishingComboTarget.json
│ │ ├── SpearfishingItem.json
│ │ ├── SpearfishingNotebook.json
│ │ ├── SpearfishingRecordPage.json
│ │ ├── SpearfishingSilhouette.json
│ │ ├── SpecialShop.json
│ │ ├── SpecialShopItemCategory.json
│ │ ├── Stain.json
│ │ ├── StainTransient.json
│ │ ├── StanceChange.json
│ │ ├── Status.json
│ │ ├── StatusHitEffect.json
│ │ ├── StatusLoopVFX.json
│ │ ├── Story.json
│ │ ├── SubmarineExploration.json
│ │ ├── SubmarineMap.json
│ │ ├── SubmarinePart.json
│ │ ├── SubmarineRank.json
│ │ ├── SwitchTalk.json
│ │ ├── SwitchTalkVariation.json
│ │ ├── TelepoRelay.json
│ │ ├── TerritoryType.json
│ │ ├── TerritoryTypeTelepo.json
│ │ ├── TerritoryTypeTransient.json
│ │ ├── TextCommand.json
│ │ ├── TextCommandParam.json
│ │ ├── TiltParam.json
│ │ ├── Title.json
│ │ ├── TofuEditParam.json
│ │ ├── TofuObject.json
│ │ ├── TofuObjectCategory.json
│ │ ├── TofuPreset.json
│ │ ├── TofuPresetCategory.json
│ │ ├── TofuPresetObject.json
│ │ ├── Tomestones.json
│ │ ├── TomestonesItem.json
│ │ ├── TopicSelect.json
│ │ ├── Town.json
│ │ ├── Trait.json
│ │ ├── TraitRecast.json
│ │ ├── TraitTransient.json
│ │ ├── Transformation.json
│ │ ├── Treasure.json
│ │ ├── TreasureHuntRank.json
│ │ ├── TreasureModel.json
│ │ ├── TreasureSpot.json
│ │ ├── Tribe.json
│ │ ├── TripleTriad.json
│ │ ├── TripleTriadCard.json
│ │ ├── TripleTriadCardObtain.json
│ │ ├── TripleTriadCardRarity.json
│ │ ├── TripleTriadCardResident.json
│ │ ├── TripleTriadCardType.json
│ │ ├── TripleTriadCompetition.json
│ │ ├── TripleTriadResident.json
│ │ ├── TripleTriadRule.json
│ │ ├── Tutorial.json
│ │ ├── TutorialDPS.json
│ │ ├── TutorialHealer.json
│ │ ├── TutorialTank.json
│ │ ├── UDS_Event.json
│ │ ├── UDS_Property.json
│ │ ├── UIColor.json
│ │ ├── UIConst.json
│ │ ├── UILevelLookup.json
│ │ ├── VFX.json
│ │ ├── VVDData.json
│ │ ├── VVDNotebookContents.json
│ │ ├── VVDNotebookSeries.json
│ │ ├── VVDRouteData.json
│ │ ├── VVDVariantAction.json
│ │ ├── VaseFlower.json
│ │ ├── Warp.json
│ │ ├── WarpCondition.json
│ │ ├── WarpLogic.json
│ │ ├── WeaponTimeline.json
│ │ ├── Weather.json
│ │ ├── WeatherGroup.json
│ │ ├── WeatherRate.json
│ │ ├── WeatherReportReplace.json
│ │ ├── WebGuidance.json
│ │ ├── WebURL.json
│ │ ├── WeddingBGM.json
│ │ ├── WeeklyBingoOrderData.json
│ │ ├── WeeklyBingoRewardData.json
│ │ ├── WeeklyBingoText.json
│ │ ├── WeeklyLotBonus.json
│ │ ├── World.json
│ │ ├── WorldDCGroupType.json
│ │ ├── YKW.json
│ │ ├── YardCatalogCategory.json
│ │ ├── YardCatalogItemList.json
│ │ ├── ZoneSharedGroup.json
│ │ └── game.ver
│ ├── EorzeaDateTime.Formatter.cs
│ ├── EorzeaDateTime.cs
│ ├── Ex/
│ │ ├── Column.cs
│ │ ├── DataReader.cs
│ │ ├── DataReaders/
│ │ │ ├── DelegateDataReader.cs
│ │ │ ├── PackedBooleanDataReader.cs
│ │ │ └── StringDataReader.cs
│ │ ├── DataRowBase.cs
│ │ ├── DataSheet.Enumerator.cs
│ │ ├── DataSheet.cs
│ │ ├── ExCollection.cs
│ │ ├── Header.cs
│ │ ├── IDataRow.cs
│ │ ├── IDataSheet.Generic.cs
│ │ ├── IDataSheet.cs
│ │ ├── IMultiRow.cs
│ │ ├── IMultiSheet.Generic.cs
│ │ ├── IMultiSheet.cs
│ │ ├── IRow.cs
│ │ ├── ISheet.Generic.cs
│ │ ├── ISheet.cs
│ │ ├── Language.cs
│ │ ├── MultiRow.cs
│ │ ├── MultiSheet.Enumerator.cs
│ │ ├── MultiSheet.cs
│ │ ├── PartialDataSheet.Enumerator.cs
│ │ ├── PartialDataSheet.cs
│ │ ├── Relational/
│ │ │ ├── Definition/
│ │ │ │ ├── GroupDataDefinition.cs
│ │ │ │ ├── IDataDefinition.cs
│ │ │ │ ├── PositionedDataDefinition.cs
│ │ │ │ ├── RelationDefinition.cs
│ │ │ │ ├── RepeatDataDefinition.cs
│ │ │ │ ├── SheetDefinition.cs
│ │ │ │ ├── SingleDataDefinition.cs
│ │ │ │ └── ViewDefinition.cs
│ │ │ ├── IRelationalDataRow.cs
│ │ │ ├── IRelationalDataSheet.Generic.cs
│ │ │ ├── IRelationalDataSheet.cs
│ │ │ ├── IRelationalMultiRow.cs
│ │ │ ├── IRelationalMultiSheet.Generic.cs
│ │ │ ├── IRelationalMultiSheet.cs
│ │ │ ├── IRelationalRow.cs
│ │ │ ├── IRelationalSheet.Generic.cs
│ │ │ ├── IRelationalSheet.cs
│ │ │ ├── IValueConverter.cs
│ │ │ ├── RelationalColumn.cs
│ │ │ ├── RelationalDataIndex.cs
│ │ │ ├── RelationalDataSheet.cs
│ │ │ ├── RelationalExCollection.cs
│ │ │ ├── RelationalHeader.cs
│ │ │ ├── RelationalMultiRow.cs
│ │ │ ├── RelationalMultiSheet.cs
│ │ │ ├── RelationalPartialDataSheet.cs
│ │ │ ├── Update/
│ │ │ │ ├── ChangeType.cs
│ │ │ │ ├── Changes/
│ │ │ │ │ ├── DefinitionMoved.cs
│ │ │ │ │ ├── DefinitionRemoved.cs
│ │ │ │ │ ├── FieldChanged.cs
│ │ │ │ │ ├── RowAdded.cs
│ │ │ │ │ ├── RowRemoved.cs
│ │ │ │ │ ├── SheetLanguageAdded.cs
│ │ │ │ │ ├── SheetLanguageRemoved.cs
│ │ │ │ │ ├── SheetRemoved.cs
│ │ │ │ │ └── SheetTypeChanged.cs
│ │ │ │ ├── ColumnComparer.cs
│ │ │ │ ├── Comparer.cs
│ │ │ │ ├── DefinitionUpdater.cs
│ │ │ │ ├── IChange.cs
│ │ │ │ ├── RelationUpdater.cs
│ │ │ │ ├── SheetComparer.cs
│ │ │ │ ├── SheetUpdater.cs
│ │ │ │ └── UpdateProgress.cs
│ │ │ └── ValueConverters/
│ │ │ ├── ColorConverter.cs
│ │ │ ├── ComplexLinkConverter.cs
│ │ │ ├── GenericReferenceConverter.cs
│ │ │ ├── IconConverter.cs
│ │ │ ├── MultiReferenceConverter.cs
│ │ │ ├── QuadConverter.cs
│ │ │ ├── SheetLinkConverter.cs
│ │ │ └── TomestoneOrItemReferenceConverter.cs
│ │ ├── Variant1/
│ │ │ ├── DataRow.cs
│ │ │ └── RelationalDataRow.cs
│ │ └── Variant2/
│ │ ├── DataRow.cs
│ │ ├── RelationalDataRow.cs
│ │ └── SubRow.cs
│ ├── Graphics/
│ │ ├── Bone.cs
│ │ ├── BoundingBox.cs
│ │ ├── ColorMap.cs
│ │ ├── Exports/
│ │ │ ├── ModelExport.cs
│ │ │ └── Obj.cs
│ │ ├── ImcFile.cs
│ │ ├── ImcPart.cs
│ │ ├── ImcVariant.cs
│ │ ├── Lgb/
│ │ │ ├── ILgbEntry.cs
│ │ │ ├── LgbENpcEntry.cs
│ │ │ ├── LgbEntryType.cs
│ │ │ ├── LgbEventObjectEntry.cs
│ │ │ ├── LgbFile.cs
│ │ │ ├── LgbGimmickEntry.cs
│ │ │ ├── LgbGroup.cs
│ │ │ ├── LgbLightEntry.cs
│ │ │ ├── LgbModelEntry.cs
│ │ │ └── LgbVfxEntry.cs
│ │ ├── Material.cs
│ │ ├── MaterialDefinition.cs
│ │ ├── MaterialHeader.cs
│ │ ├── MaterialMetadataHeader.cs
│ │ ├── MaterialTextureParameter.cs
│ │ ├── Mesh.cs
│ │ ├── MeshHeader.cs
│ │ ├── MeshPart.cs
│ │ ├── MeshPartHeader.cs
│ │ ├── Model.cs
│ │ ├── ModelAttribute.cs
│ │ ├── ModelBoundingBoxes.cs
│ │ ├── ModelDefinition.cs
│ │ ├── ModelDefinitionHeader.cs
│ │ ├── ModelFile.cs
│ │ ├── ModelHeader.cs
│ │ ├── ModelQuality.cs
│ │ ├── ModelVariantIdentifier.cs
│ │ ├── PapAnimation.cs
│ │ ├── PapFile.cs
│ │ ├── Pcb/
│ │ │ ├── IPcbBlockData.cs
│ │ │ ├── PcbBlockData.cs
│ │ │ ├── PcbBlockDataType.cs
│ │ │ ├── PcbBlockEntry.cs
│ │ │ └── PcbFile.cs
│ │ ├── Sgb/
│ │ │ ├── ISgbData.cs
│ │ │ ├── ISgbGroupEntry.cs
│ │ │ ├── SgbDataType.cs
│ │ │ ├── SgbFile.cs
│ │ │ ├── SgbGimmickEntry.cs
│ │ │ ├── SgbGroup.cs
│ │ │ ├── SgbGroup1CEntry.cs
│ │ │ ├── SgbGroupEntryType.cs
│ │ │ ├── SgbLightEntry.cs
│ │ │ ├── SgbModelEntry.cs
│ │ │ └── SgbVfxEntry.cs
│ │ ├── ShPk/
│ │ │ ├── Parameter.cs
│ │ │ ├── ParameterHeader.cs
│ │ │ ├── ParameterType.cs
│ │ │ ├── ShPkFile.cs
│ │ │ ├── ShPkHeader.cs
│ │ │ ├── ShaderHeader.cs
│ │ │ ├── ShaderParameterReference.cs
│ │ │ └── ShaderType.cs
│ │ ├── SklbFile.cs
│ │ ├── Territory.cs
│ │ ├── TerritoryParts/
│ │ │ └── Terrain.cs
│ │ ├── TransformedModel.cs
│ │ ├── Unknowns/
│ │ │ ├── BoneIndices.cs
│ │ │ ├── BoneList.cs
│ │ │ ├── MaterialStruct1.cs
│ │ │ ├── MaterialStruct2.cs
│ │ │ ├── ModelStruct1.cs
│ │ │ ├── ModelStruct2.cs
│ │ │ ├── ModelStruct3.cs
│ │ │ ├── ModelStruct5.cs
│ │ │ ├── ModelStruct6.cs
│ │ │ └── ModelStruct7.cs
│ │ ├── Vector2.cs
│ │ ├── Vector3.cs
│ │ ├── Vector4.cs
│ │ ├── Vertex.cs
│ │ ├── VertexAttribute.cs
│ │ ├── VertexDataType.cs
│ │ ├── VertexFormat.cs
│ │ ├── VertexFormatElement.cs
│ │ └── VertexReader.cs
│ ├── HalfHelper.cs
│ ├── IO/
│ │ ├── Directory.Enumeration.cs
│ │ ├── Directory.cs
│ │ ├── EmptyFile.cs
│ │ ├── File.cs
│ │ ├── FileCommonHeader.cs
│ │ ├── FileDefault.cs
│ │ ├── FileFactory.cs
│ │ ├── FileType.cs
│ │ ├── Hash.cs
│ │ ├── IIndexFile.cs
│ │ ├── IPackSource.cs
│ │ ├── Index.cs
│ │ ├── Index2.cs
│ │ ├── Index2File.cs
│ │ ├── Index2Header.cs
│ │ ├── Index2Source.Enumerator.cs
│ │ ├── Index2Source.cs
│ │ ├── IndexDirectory.cs
│ │ ├── IndexFile.cs
│ │ ├── IndexHeader.cs
│ │ ├── IndexSource.Enumerator.cs
│ │ ├── IndexSource.cs
│ │ ├── Pack.cs
│ │ ├── PackCollection.cs
│ │ └── PackIdentifier.cs
│ ├── Imaging/
│ │ ├── GftdEntry.cs
│ │ ├── GraphicsFileTextureDefinition.cs
│ │ ├── IconHelper.cs
│ │ ├── ImageConverter.cs
│ │ ├── ImageFile.cs
│ │ ├── ImageFormat.cs
│ │ └── ImageHeader.cs
│ ├── Libra/
│ │ ├── Achievement.cs
│ │ ├── AchievementCategory.cs
│ │ ├── AchievementKind.cs
│ │ ├── Action.cs
│ │ ├── BNpcName.Parse.cs
│ │ ├── BNpcName.cs
│ │ ├── BNpcName_PlaceName.cs
│ │ ├── BaseParam.cs
│ │ ├── BeastTribe.cs
│ │ ├── ClassJob.cs
│ │ ├── ClassJobCategory.cs
│ │ ├── ClassJob_ClassJobCategory.cs
│ │ ├── Colosseum.cs
│ │ ├── ContentRoulette.cs
│ │ ├── ContentType.cs
│ │ ├── CraftType.cs
│ │ ├── ENpcResident.Parse.cs
│ │ ├── ENpcResident.cs
│ │ ├── ENpcResident_PlaceName.cs
│ │ ├── ENpcResident_Quest.cs
│ │ ├── Emote.cs
│ │ ├── Entities.cs
│ │ ├── FCHierarchy.cs
│ │ ├── FCRank.cs
│ │ ├── FCReputation.cs
│ │ ├── Frontline01.cs
│ │ ├── GCRankGridaniaFemaleText.cs
│ │ ├── GCRankGridaniaMaleText.cs
│ │ ├── GCRankLimsaFemaleText.cs
│ │ ├── GCRankLimsaMaleText.cs
│ │ ├── GCRankUldahFemaleText.cs
│ │ ├── GCRankUldahMaleText.cs
│ │ ├── Gathering.cs
│ │ ├── GatheringType.cs
│ │ ├── GeneralAction.cs
│ │ ├── GrandCompany.cs
│ │ ├── GuardianDeity.cs
│ │ ├── GuildOrder.cs
│ │ ├── InstanceContent.cs
│ │ ├── InstanceContentType.cs
│ │ ├── Item.Parse.cs
│ │ ├── Item.cs
│ │ ├── ItemCategory.cs
│ │ ├── ItemSery.cs
│ │ ├── ItemSpecialBonu.cs
│ │ ├── ItemUICategory.cs
│ │ ├── ItemUIKind.cs
│ │ ├── Item_ClassJob.cs
│ │ ├── JournalCategory.cs
│ │ ├── JournalGenre.cs
│ │ ├── JsonReaderExtensions.cs
│ │ ├── LibraModel.Context.cs
│ │ ├── LibraModel.Context.tt
│ │ ├── LibraModel.Designer.cs
│ │ ├── LibraModel.cs
│ │ ├── LibraModel.edmx
│ │ ├── LibraModel.edmx.diagram
│ │ ├── LibraModel.tt
│ │ ├── LodestoneSystemDefine.cs
│ │ ├── NotebookDivision.cs
│ │ ├── PlaceName.cs
│ │ ├── Quest.cs
│ │ ├── QuestWebEx.cs
│ │ ├── QuestWebType.cs
│ │ ├── Quest_ClassJob.cs
│ │ ├── Race.cs
│ │ ├── Recipe.cs
│ │ ├── RecipeElement.cs
│ │ ├── Shop.cs
│ │ ├── Status.cs
│ │ ├── Title.cs
│ │ ├── Tomestone.cs
│ │ └── Town.cs
│ ├── OrderedBitConverter.cs
│ ├── Range.cs
│ ├── SaintCoinach.csproj
│ ├── Sound/
│ │ ├── ScdAdpcmEntry.cs
│ │ ├── ScdCodec.cs
│ │ ├── ScdEntry.cs
│ │ ├── ScdEntryHeader.cs
│ │ ├── ScdFile.cs
│ │ ├── ScdHeader.cs
│ │ ├── ScdOggCryptType.cs
│ │ └── ScdOggEntry.cs
│ ├── Text/
│ │ ├── DecodeExpressionType.cs
│ │ ├── DefaultEvaluationFunctionProvider.cs
│ │ ├── EvaluationHelper.cs
│ │ ├── EvaluationParameters.cs
│ │ ├── Expressions/
│ │ │ ├── CloseTag.cs
│ │ │ ├── ExpressionCollection.cs
│ │ │ ├── GenericExpression.cs
│ │ │ ├── IValueExpression.cs
│ │ │ ├── ObjectWithDisplay.cs
│ │ │ ├── OpenTag.cs
│ │ │ └── SurroundedExpression.cs
│ │ ├── IEvaluationFunctionProvider.cs
│ │ ├── IExpression.cs
│ │ ├── INode.cs
│ │ ├── IntegerType.cs
│ │ ├── NodeFlags.cs
│ │ ├── Nodes/
│ │ │ ├── ArgumentCollection.cs
│ │ │ ├── CloseTag.cs
│ │ │ ├── Comparison.cs
│ │ │ ├── DefaultElement.cs
│ │ │ ├── EmptyElement.cs
│ │ │ ├── GenericElement.cs
│ │ │ ├── IConditionalNode.cs
│ │ │ ├── IExpressionNode.cs
│ │ │ ├── INodeVisitor.cs
│ │ │ ├── INodeWithArguments.cs
│ │ │ ├── INodeWithChildren.cs
│ │ │ ├── IStaticNode.cs
│ │ │ ├── IfElement.cs
│ │ │ ├── IfEqualsElement.cs
│ │ │ ├── OpenTag.cs
│ │ │ ├── Parameter.cs
│ │ │ ├── StaticByteArray.cs
│ │ │ ├── StaticInteger.cs
│ │ │ ├── StaticString.cs
│ │ │ ├── SwitchElement.cs
│ │ │ └── TopLevelParameter.cs
│ │ ├── Parameters/
│ │ │ ├── ObjectParameters.cs
│ │ │ ├── ParameterBase.cs
│ │ │ └── PlayerParameters.cs
│ │ ├── Processor/
│ │ │ ├── Expressions/
│ │ │ │ ├── EmptyExpression.cs
│ │ │ │ ├── ExpressionCollection.cs
│ │ │ │ └── StaticExpression.cs
│ │ │ └── IExpression.cs
│ │ ├── StringTokens.cs
│ │ ├── TagType.cs
│ │ ├── XivString.cs
│ │ └── XivStringDecoder.cs
│ ├── UpdateReport.cs
│ ├── Xiv/
│ │ ├── Achievement.cs
│ │ ├── AchievementCategory.cs
│ │ ├── AchievementKind.cs
│ │ ├── Action.cs
│ │ ├── ActionBase.cs
│ │ ├── ActionCategory.cs
│ │ ├── ActionTransient.cs
│ │ ├── Addon.cs
│ │ ├── Adventure.cs
│ │ ├── AetherCurrent.cs
│ │ ├── AirshipExplorationLevel.cs
│ │ ├── AirshipExplorationLog.cs
│ │ ├── AirshipExplorationParamType.cs
│ │ ├── AirshipExplorationPoint.cs
│ │ ├── BGM.cs
│ │ ├── BNpc.cs
│ │ ├── BNpcBase.cs
│ │ ├── BNpcData.cs
│ │ ├── BNpcLocation.cs
│ │ ├── BNpcName.cs
│ │ ├── BaseParam.cs
│ │ ├── BeastReputationRank.cs
│ │ ├── BeastTribe.cs
│ │ ├── BuddyAction.cs
│ │ ├── BuddyEquip.cs
│ │ ├── CharaMakeCustomize.cs
│ │ ├── CharaMakeType.cs
│ │ ├── ChocoboRace.cs
│ │ ├── ChocoboRaceAbility.cs
│ │ ├── ChocoboRaceAbilityType.cs
│ │ ├── ChocoboRaceItem.cs
│ │ ├── ChocoboRaceRank.cs
│ │ ├── ChocoboRaceStatus.cs
│ │ ├── ChocoboRaceTerritory.cs
│ │ ├── ClassJob.cs
│ │ ├── ClassJobActionBase.cs
│ │ ├── ClassJobCategory.cs
│ │ ├── Collections/
│ │ │ ├── BNpcCollection.cs
│ │ │ ├── ClassJobActionCollection.cs
│ │ │ ├── ENpcCollection.cs
│ │ │ ├── EquipSlotCollection.cs
│ │ │ ├── ItemCollection.cs
│ │ │ └── ShopCollection.cs
│ │ ├── Companion.cs
│ │ ├── CompanionTransient.cs
│ │ ├── CompanyAction.cs
│ │ ├── CompanyCraftDraft.cs
│ │ ├── CompanyCraftDraftCategory.cs
│ │ ├── CompanyCraftDraftCategoryTxt.cs
│ │ ├── CompanyCraftManufactoryState.cs
│ │ ├── CompanyCraftPart.cs
│ │ ├── CompanyCraftProcess.Request.cs
│ │ ├── CompanyCraftProcess.cs
│ │ ├── CompanyCraftSequence.cs
│ │ ├── CompanyCraftSupplyItem.cs
│ │ ├── CompanyCraftType.cs
│ │ ├── ContentBase.cs
│ │ ├── ContentFinderCondition.cs
│ │ ├── ContentMemberType.cs
│ │ ├── ContentReward.cs
│ │ ├── ContentRoulette.cs
│ │ ├── ContentType.cs
│ │ ├── CraftAction.cs
│ │ ├── CraftLeve.cs
│ │ ├── CraftLeveItem.cs
│ │ ├── CraftLevelDifference.cs
│ │ ├── CraftType.cs
│ │ ├── CustomTalk.cs
│ │ ├── ENpc.cs
│ │ ├── ENpcBase.cs
│ │ ├── ENpcResident.cs
│ │ ├── EObj.cs
│ │ ├── Emote.cs
│ │ ├── EmoteCategory.cs
│ │ ├── EquipSlot.cs
│ │ ├── EquipSlotCategory.cs
│ │ ├── EventAction.cs
│ │ ├── EventItem.cs
│ │ ├── FCRank.cs
│ │ ├── Fate.cs
│ │ ├── FccShop.cs
│ │ ├── FishParameter.cs
│ │ ├── FishingSpot.cs
│ │ ├── GCScripShopCategory.cs
│ │ ├── GCScripShopItem.cs
│ │ ├── GCShop.cs
│ │ ├── GCShopItemCategory.cs
│ │ ├── GatheringCondition.cs
│ │ ├── GatheringExp.cs
│ │ ├── GatheringItem.cs
│ │ ├── GatheringItemBase.cs
│ │ ├── GatheringNotebookList.cs
│ │ ├── GatheringNotebookRegion.cs
│ │ ├── GatheringPoint.cs
│ │ ├── GatheringPointBase.cs
│ │ ├── GatheringPointBonus.cs
│ │ ├── GatheringPointBonusType.cs
│ │ ├── GatheringPointName.cs
│ │ ├── GatheringSubCategory.cs
│ │ ├── GatheringType.cs
│ │ ├── GeneralAction.cs
│ │ ├── GenericLocation.cs
│ │ ├── GilShop.cs
│ │ ├── GilShopItem.cs
│ │ ├── GoldSaucerTextData.cs
│ │ ├── GrandCompany.cs
│ │ ├── GrandCompanyRank.cs
│ │ ├── GuardianDeity.cs
│ │ ├── HousingFurniture.cs
│ │ ├── HousingItem.cs
│ │ ├── HousingItemCategory.cs
│ │ ├── HousingLayoutLimit.cs
│ │ ├── HousingYardObject.cs
│ │ ├── IContentReward.cs
│ │ ├── IItemSource.cs
│ │ ├── ILocatable.cs
│ │ ├── ILocation.cs
│ │ ├── IParameterObject.cs
│ │ ├── IQuantifiable.cs
│ │ ├── IQuantifiableXivString.cs
│ │ ├── IShop.cs
│ │ ├── IShopListing.cs
│ │ ├── IShopListingItem.cs
│ │ ├── IXivRow.cs
│ │ ├── IXivSheet.Generic.cs
│ │ ├── IXivSheet.cs
│ │ ├── IXivSubRow.cs
│ │ ├── InstanceContent.cs
│ │ ├── InstanceContentData.Fight.cs
│ │ ├── InstanceContentData.RewardItem.cs
│ │ ├── InstanceContentData.Treasure.cs
│ │ ├── InstanceContentData.cs
│ │ ├── Item.cs
│ │ ├── ItemAction.cs
│ │ ├── ItemActions/
│ │ │ ├── AchievementScroll.cs
│ │ │ ├── AdventureBook.cs
│ │ │ ├── AetherytePendulum.cs
│ │ │ ├── AttributeReset.cs
│ │ │ ├── BuddyEquipUnlock.cs
│ │ │ ├── BuddySummon.cs
│ │ │ ├── ChocoboActionReset.cs
│ │ │ ├── ChocoboFeed.cs
│ │ │ ├── ChocoboLevelCapIncrease.cs
│ │ │ ├── CompanionUnlock.cs
│ │ │ ├── CompanyEffect.cs
│ │ │ ├── CustomizeUnlock.cs
│ │ │ ├── DesynthSkillReset.cs
│ │ │ ├── Enhancement.cs
│ │ │ ├── EquipmentCoffer.cs
│ │ │ ├── EternalBondInvitation.cs
│ │ │ ├── EternityRing.cs
│ │ │ ├── Fantasia.cs
│ │ │ ├── FateContentAction.cs
│ │ │ ├── FieldNoteUnlock.cs
│ │ │ ├── Fireworks.cs
│ │ │ ├── FolkloreBook.cs
│ │ │ ├── Food.cs
│ │ │ ├── FriendlyEffect.cs
│ │ │ ├── GpRecovery.cs
│ │ │ ├── Heavenscracker.cs
│ │ │ ├── HostileEffect.cs
│ │ │ ├── HpMpRecovery.cs
│ │ │ ├── HpRecovery.cs
│ │ │ ├── ItemRoulette.cs
│ │ │ ├── MgpCard.cs
│ │ │ ├── MountUnlock.cs
│ │ │ ├── MpRecovery.cs
│ │ │ ├── OrchestrionRollUnlock.cs
│ │ │ ├── OrnamentUnlock.cs
│ │ │ ├── PointRecovery.cs
│ │ │ ├── Raise.cs
│ │ │ ├── RealmRebornRed.cs
│ │ │ ├── RecipeBookUnlock.cs
│ │ │ ├── Sanction.cs
│ │ │ ├── SphereScroll.cs
│ │ │ ├── StatusRemoval.cs
│ │ │ ├── SustainPotion.cs
│ │ │ ├── TeleportationTicket.cs
│ │ │ ├── TpRecovery.cs
│ │ │ └── TripleTriadCardUnlock.cs
│ │ ├── ItemBase.cs
│ │ ├── ItemComparer.cs
│ │ ├── ItemFood.cs
│ │ ├── ItemLevel.cs
│ │ ├── ItemSearchCategory.cs
│ │ ├── ItemSeries.cs
│ │ ├── ItemSpecialBonus.cs
│ │ ├── ItemUICategory.cs
│ │ ├── Items/
│ │ │ ├── Accessory.cs
│ │ │ ├── Armour.cs
│ │ │ ├── CraftingTool.cs
│ │ │ ├── Equipment.cs
│ │ │ ├── GatheringTool.cs
│ │ │ ├── Housing.cs
│ │ │ ├── MagicWeapon.cs
│ │ │ ├── MateriaItem.cs
│ │ │ ├── PhysicalWeapon.cs
│ │ │ ├── Shield.cs
│ │ │ ├── SoulCrystal.cs
│ │ │ ├── Usable.cs
│ │ │ └── Weapon.cs
│ │ ├── JournalCategory.cs
│ │ ├── JournalGenre.cs
│ │ ├── JournalSection.cs
│ │ ├── Leve.cs
│ │ ├── LeveAssignmentType.cs
│ │ ├── LeveClient.cs
│ │ ├── LeveRewardItem.cs
│ │ ├── LeveRewardItemGroup.cs
│ │ ├── LeveVfx.cs
│ │ ├── Level.cs
│ │ ├── LogFilter.cs
│ │ ├── LogKind.cs
│ │ ├── LogKindCategoryText.cs
│ │ ├── LogMessage.cs
│ │ ├── MYCWarResultNotebook.cs
│ │ ├── MainCommand.cs
│ │ ├── MainCommandCategory.cs
│ │ ├── Map.cs
│ │ ├── MasterpieceSupplyDuty.CollectableItem.cs
│ │ ├── MasterpieceSupplyDuty.cs
│ │ ├── Materia.cs
│ │ ├── MinionRace.cs
│ │ ├── MinionSkillType.cs
│ │ ├── ModelChara.cs
│ │ ├── MonsterNote.cs
│ │ ├── MonsterNoteTarget.cs
│ │ ├── Mount.cs
│ │ ├── NpcEquip.cs
│ │ ├── OnlineStatus.cs
│ │ ├── Ornament.cs
│ │ ├── ParamGrow.cs
│ │ ├── Parameter.cs
│ │ ├── ParameterCollection.cs
│ │ ├── ParameterType.cs
│ │ ├── ParameterValue.cs
│ │ ├── ParameterValueFixed.cs
│ │ ├── ParameterValueRelative.cs
│ │ ├── ParameterValueRelativeLimited.cs
│ │ ├── PlaceName.cs
│ │ ├── PrerequisiteQuestsRequirement.cs
│ │ ├── PrerequisiteQuestsRequirementType.cs
│ │ ├── ProbabilityPair.cs
│ │ ├── Quad.cs
│ │ ├── Quest.cs
│ │ ├── QuestRepeatInterval.cs
│ │ ├── QuestRequirements.ClassJobRequirement.cs
│ │ ├── QuestRequirements.InstanceContentRequirement.cs
│ │ ├── QuestRequirements.PreviousQuestRequirement.cs
│ │ ├── QuestRequirements.cs
│ │ ├── QuestRewardGroupType.cs
│ │ ├── QuestRewardItem.cs
│ │ ├── QuestRewardItemGroup.cs
│ │ ├── QuestRewardOther.cs
│ │ ├── QuestRewards.cs
│ │ ├── Race.cs
│ │ ├── RacingChocoboItem.cs
│ │ ├── RacingChocoboName.cs
│ │ ├── RacingChocoboNameCategory.cs
│ │ ├── RacingChocoboNameInfo.cs
│ │ ├── RacingChocoboParam.cs
│ │ ├── Recipe.cs
│ │ ├── RecipeElement.cs
│ │ ├── RecipeIngredient.cs
│ │ ├── RecipeIngredientType.cs
│ │ ├── RecipeLevel.cs
│ │ ├── RecipeLevelTable.cs
│ │ ├── RelicNote.cs
│ │ ├── RelicNoteCategory.cs
│ │ ├── RelicNoteCategoryText.cs
│ │ ├── RetainerTask.cs
│ │ ├── RetainerTaskBase.cs
│ │ ├── RetainerTaskNormal.cs
│ │ ├── RetainerTaskRandom.cs
│ │ ├── Salvage.cs
│ │ ├── Sheets/
│ │ │ ├── InventoryItemSheet.cs
│ │ │ └── ItemActionSheet.cs
│ │ ├── ShopListingItem.cs
│ │ ├── SpearfishingItem.cs
│ │ ├── SpecialShop.cs
│ │ ├── SpecialShopListing.cs
│ │ ├── Stain.cs
│ │ ├── Status.cs
│ │ ├── TerritoryType.cs
│ │ ├── Title.cs
│ │ ├── Tomestone.cs
│ │ ├── TomestonesItem.cs
│ │ ├── Trait.cs
│ │ ├── Tribe.cs
│ │ ├── TripleTriad.cs
│ │ ├── TripleTriadCard.cs
│ │ ├── TripleTriadCardRarity.cs
│ │ ├── TripleTriadCardResident.cs
│ │ ├── TripleTriadCardType.cs
│ │ ├── TripleTriadCompetition.cs
│ │ ├── TripleTriadRule.cs
│ │ ├── Weather.cs
│ │ ├── WeatherRate.cs
│ │ ├── XivCollection.cs
│ │ ├── XivRow.cs
│ │ ├── XivSheet.Enumerator.cs
│ │ ├── XivSheet.cs
│ │ ├── XivSheet2.Enumerator.cs
│ │ ├── XivSheet2.cs
│ │ ├── XivSheetAttribute.cs
│ │ └── XivSubRow.cs
│ ├── app.config
│ └── packages.config
├── SaintCoinach.Cmd/
│ ├── App.config
│ ├── Commands/
│ │ ├── AllExdCommand.cs
│ │ ├── AllExdRawCommand.cs
│ │ ├── BgmCommand.cs
│ │ ├── ExdCommand.cs
│ │ ├── ExdHeaderCommand.cs
│ │ ├── FurnitureExpCommand.cs
│ │ ├── HDUiCommand.cs
│ │ ├── ImageCommand.cs
│ │ ├── LanguageCommand.cs
│ │ ├── MapCommand.cs
│ │ ├── RawCommand.cs
│ │ ├── RawExdCommand.cs
│ │ ├── SqlExport.cs
│ │ └── UiCommand.cs
│ ├── ExdHelper.cs
│ ├── Program.cs
│ ├── Properties/
│ │ ├── Settings.Designer.cs
│ │ └── Settings.settings
│ └── SaintCoinach.Cmd.csproj
├── SaintCoinach.Graphics.Viewer/
│ ├── AnimatedModel.cs
│ ├── Animation.cs
│ ├── AnimationContainer.cs
│ ├── AnimationPlayer.cs
│ ├── Camera.cs
│ ├── Component.cs
│ ├── ComponentContainer.cs
│ ├── Content/
│ │ ├── BgColorChangeMaterial.cs
│ │ ├── BgMaterial.cs
│ │ ├── CharacterMaterial.cs
│ │ ├── ContentMesh.cs
│ │ ├── ContentMeshPart.cs
│ │ ├── ContentModel.cs
│ │ ├── ContentSgb.cs
│ │ ├── ContentTerritory.cs
│ │ ├── CrystalMaterial.cs
│ │ ├── Cube.cs
│ │ ├── HairMaterial.cs
│ │ ├── IrisMaterial.cs
│ │ ├── MaterialBase.cs
│ │ ├── PrimitiveMesh.cs
│ │ ├── PrimitiveModel.cs
│ │ └── SkinMaterial.cs
│ ├── Data/
│ │ ├── CustomizeParameters.cs
│ │ └── ParametersBase.cs
│ ├── Drawable3DComponent.cs
│ ├── EffectFactory.cs
│ ├── Effects/
│ │ ├── BgColorChangeEffect.cs
│ │ ├── BgEffect.cs
│ │ ├── CharacterEffect.cs
│ │ ├── CrystalEffect.cs
│ │ ├── CustomizeParameterEffectVariable.cs
│ │ ├── DirectionalLight.cs
│ │ ├── EffectBase.cs
│ │ ├── EffectDirectionalLightVariable.cs
│ │ ├── EffectTextureVariable.cs
│ │ ├── HLSL/
│ │ │ ├── BasicEffect.fx
│ │ │ ├── Bg.fx
│ │ │ ├── BgColorChange.fx
│ │ │ ├── BgUvScroll.fx
│ │ │ ├── Character.fx
│ │ │ ├── Common.Skinned.fxh
│ │ │ ├── Common.fxh
│ │ │ ├── Crystal.fx
│ │ │ ├── CustomizeParameter.fxh
│ │ │ ├── Hair.fx
│ │ │ ├── Iris.fx
│ │ │ ├── Lighting.fxh
│ │ │ ├── Skin.fx
│ │ │ └── Structures.fxh
│ │ ├── HairEffect.cs
│ │ ├── IrisEffect.cs
│ │ ├── SkinEffect.cs
│ │ └── SkinnedEffect.cs
│ ├── Engine.cs
│ ├── EngineTime.cs
│ ├── FormEngine.cs
│ ├── FormInputService.cs
│ ├── IComponent.cs
│ ├── IContentComponent.cs
│ ├── IDrawable3DComponent.cs
│ ├── IImageRendererSource.cs
│ ├── IInputService.cs
│ ├── IUpdateableComponent.cs
│ ├── ImageRenderer.cs
│ ├── Interop/
│ │ ├── FbxExport.cs
│ │ ├── HavokInterop.cs
│ │ ├── InteropAnimation.cs
│ │ ├── InteropMesh.cs
│ │ ├── InteropTransform.cs
│ │ ├── InteropVector4.cs
│ │ └── InteropVertex.cs
│ ├── Keyboard.cs
│ ├── MaterialFactory.cs
│ ├── ModelFactory.cs
│ ├── Mouse.cs
│ ├── MouseState.cs
│ ├── ParametersExtensions.cs
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ ├── RendererSources/
│ │ ├── BaseImageRendererSource.cs
│ │ ├── EquipmentImageRendererSource.cs
│ │ └── MonsterImageRendererSource.cs
│ ├── SaintCoinach.Graphics.Viewer.csproj
│ ├── Skeleton.cs
│ ├── TextureFactory.cs
│ ├── VectorConverter.cs
│ ├── Vertex3D.cs
│ └── app.config
└── SaintCoinach.sln
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
# Code
[*.cs]
indent_size = 4
indent_style = space
csharp_new_line_before_open_brace = all:warning
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.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
================================================
FILE: .github/RELEASE.md
================================================
This is an automated SaintCoinach release based on recent changes.
Please note that your Anti-Virus program may detect SaintCoinach as a false positive.
================================================
FILE: .github/workflows/build.yml
================================================
name: Build SaintCoinach
on: [push, pull_request]
concurrency: build-${{ github.ref }}
jobs:
build:
name: Build on Windows
runs-on: windows-2025
steps:
- uses: actions/checkout@v2
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: '7.x.x'
- name: Define Version
id: define-version
run: |
$env:COMMIT = $env:GITHUB_SHA.Substring(0, 7)
echo "::set-output name=commit::$env:COMMIT"
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build -c Release
- name: Create Release ZIPs
if: ${{ github.ref == 'refs/heads/master' }}
run: |
mkdir release-out
Compress-Archive -Path .\Godbert\bin\Release\net7.0-windows\* -DestinationPath .\release-out\Godbert.zip -Force
Compress-Archive -Path .\SaintCoinach.Cmd\bin\Release\net7.0\* -DestinationPath .\release-out\SaintCoinach.Cmd.zip -Force
- name: Create Release
uses: softprops/action-gh-release@v1
if: ${{ github.ref == 'refs/heads/master' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
files: release-out/**
name: Release for ${{ steps.define-version.outputs.commit }}
body_path: .github\RELEASE.md
prerelease: false
tag_name: ${{ steps.define-version.outputs.commit }}
================================================
FILE: .github/workflows/json-validation.yaml
================================================
name: Validate ex JSON definitions
# This workflow is triggered on pushes to the repository.
on: [push, pull_request]
jobs:
build:
name: validate-json
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Install jsonlint
run: sudo npm install jsonlint -g
- name: Validate schemas
run: set -e; for f in $(find SaintCoinach/Definitions/ -name *.json -print); do echo -n "$f - "; jsonlint $f -q; echo "OK!"; done
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Roslyn cache directories
*.ide/
# 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
*_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
*.opensdf
*.sdf
*.cachefile
.vs/
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# 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 addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# 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
# 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/
# If using the old MSBuild-Integrated Package Restore, uncomment this:
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
# 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/
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows
# =========================
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# DX Things
*.tkb
*.StyleCop
# JetBrains
.idea
SaintCoinach.Cmd/Properties/launchSettings.json
================================================
FILE: DotSquish/Alpha.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotSquish {
internal static class Alpha {
#region DXT3
private static int FloatToInt(float a, int limit) {
// Use ANSI round-to-zero behaviour to get round-to-nearest.
var i = (int)(a + .5f);
if (i < 0)
i = 0;
else if (i > limit)
i = limit;
return i;
}
public static void CompressAlphaDxt3(byte[] rgba, byte[] target, int targetOffset, int mask) {
// Quantise and pack alpha values pairwise.
for (int i = 0; i < 8; ++i) {
// Qnatise down to 4 bits.
var alpha1 = rgba[8 * i + 3] * (15f / 255f);
var alpha2 = rgba[8 * i + 7] * (15f / 255f);
var quant1 = FloatToInt(alpha1, 15);
var quant2 = FloatToInt(alpha2, 15);
// Set alpha to zero where masked.
var bit1 = 1 << (2 * i);
var bit2 = 1 << (2 * i + 1);
if ((mask & bit1) == 0)
quant1 = 0;
if ((mask & bit2) == 0)
quant2 = 0;
// Pack into the byte.
target[targetOffset + i] = (byte)(quant1 | (quant2 << 4));
}
}
public static void DecompressAlphaDxt3(byte[] block, int blockOffset, byte[] target, int targetOffset) {
// Unpack the alpha values pairwise.
for (int i = 0; i < 8; ++i) {
// Quantise down to 4 bits.
var quant = block[blockOffset + i];
// Unpack the values.
var lo = quant & 0x0f;
var hi = quant & 0xf0;
// Convert back up to bytes.
target[targetOffset + 8 * i + 3] = (byte)(lo | (lo << 4));
target[targetOffset + 8 * i + 7] = (byte)(hi | (hi >> 4));
}
}
#endregion
#region DXT5
private static void FixRange(ref int min, ref int max, int steps) {
if (max - min < steps)
max = Math.Min(min + steps, 255);
if (max - min < steps)
min = Math.Max(0, max - steps);
}
private static int FitCodes(byte[] rgba, int mask, byte[] codes, out byte[] indices) {
indices = new byte[16];
// Fit each alpha value to the codebook.
var err = 0;
for (int i = 0; i < 16; ++i) {
// Check this pixel is valid.
var bit = 1 << i;
if ((mask & bit) == 0) {
// Use the first code.
indices[i] = 0;
continue;
}
// Find the least error and corresponding index.
var value = rgba[4 * i + 3];
var least = int.MaxValue;
var index = 0;
for (int j = 0; j < 8; ++j) {
// Get the squared error from this code.
var dist = ((int)value) - ((int)codes[j]);
dist *= dist;
// Compare with the best so far.
if (dist < least) {
least = dist;
index = j;
}
}
// Save this index and accumulate the error.
indices[i] = (byte)index;
err += least;
}
// Return the total error.
return err;
}
private static void WriteAlphaBlock(int alpha0, int alpha1, byte[] indices, byte[] target, int targetOffset) {
// Write the first two bytes.
target[targetOffset + 0] = (byte)alpha0;
target[targetOffset + 1] = (byte)alpha1;
var indOff = 0;
var retOff = 2;
for (int i = 0; i < 2; ++i) {
// Pack 8 3-bit values.
var value = 0;
for (int j = 0; j < 8; ++j) {
var index = indices[indOff++];
value |= (index << 3 * j);
}
// Store in 3 bytes
for (int j = 0; j < 3; ++j) {
var b = (value >> (8 * j)) & 0xFF;
target[targetOffset + retOff++] = (byte)b;
}
}
}
private static void WriteAlphaBlock5(int alpha0, int alpha1, byte[] indices, byte[] target, int targetOffset) {
// Check the relative values of the endpoints.
if (alpha0 > alpha1) {
var swapped = new byte[16];
for (int i = 0; i < 16; ++i) {
var index = indices[i];
if (index == 0)
swapped[i] = 1;
else if (index == 1)
swapped[i] = 0;
else if (index <= 5)
swapped[i] = (byte)(7 - index);
else
swapped[i] = index;
}
// Write the block.
WriteAlphaBlock(alpha1, alpha0, swapped, target, targetOffset);
} else {
// Write the block.
WriteAlphaBlock(alpha0, alpha1, indices, target, targetOffset);
}
}
private static void WriteAlphaBlock7(int alpha0, int alpha1, byte[] indices, byte[] target, int targetOffset) {
// Check the relative values of the endpoints.
if (alpha0 > alpha1) {
var swapped = new byte[16];
for (int i = 0; i < 16; ++i) {
var index = indices[i];
if (index == 0)
swapped[i] = 1;
else if (index == 1)
swapped[i] = 0;
else
swapped[i] = (byte)(9 - index);
}
// Write the block.
WriteAlphaBlock(alpha1, alpha0, swapped, target, targetOffset);
} else {
// Write the block.
WriteAlphaBlock(alpha0, alpha1, indices, target, targetOffset);
}
}
public static void CompressAlphaDxt5(byte[] rgba, int mask, byte[] target, int targetOffset) {
// Get the range for 5-alpha and 7-alpha interpolation.
int min5 = 255, max5 = 0;
int min7 = 255, max7 = 0;
for (int i = 0; i < 16; ++i) {
// Check this pixel is valid.
var bit = 1 << i;
if ((mask & bit) == 0)
continue;
// Incorporate into the min/max.
int value = rgba[4 * i + 3];
if (value < min7)
min7 = value;
if (value > max7)
max7 = value;
if (value != 0 && value < min5)
min5 = value;
if (value != 255 && value > max5)
max5 = value;
}
// Handle the case that no valid range was found.
if (min5 > max5)
min5 = max5;
if (min7 > max7)
min7 = max7;
// Fix the range to be the minimum in each case.
FixRange(ref min5, ref max5, 5);
FixRange(ref min7, ref max7, 7);
// Set up the 5-alpha code book.
var codes5 = new byte[8];
codes5[0] = (byte)min5;
codes5[1] = (byte)max5;
for (int i = 1; i < 5; ++i)
codes5[i + 1] = (byte)(((5 - i) * min5 + i * max5) / 5);
codes5[6] = 0;
codes5[7] = 255;
// Set up the 7-alpha code book.
var codes7 = new byte[8];
codes7[0] = (byte)min7;
codes7[1] = (byte)max7;
for (int i = 1; i < 7; ++i)
codes7[i + 1] = (byte)(((7 - i) * min7 + i * max7) / 7);
// Fit the data to both code books.
byte[] indices5, indices7;
var err5 = FitCodes(rgba, mask, codes5, out indices5);
var err7 = FitCodes(rgba, mask, codes7, out indices7);
// Save the block with least error.
if (err5 <= err7)
WriteAlphaBlock5(min5, max5, indices5, target, targetOffset);
else
WriteAlphaBlock7(min7, max7, indices7, target, targetOffset);
}
public static void DecompressAlphaDxt5(byte[] block, int blockOffset, byte[] target, int targetOffset) {
// Get the two alpha values.
var alpha0 = block[blockOffset + 0];
var alpha1 = block[blockOffset + 1];
// Compare the values to build the codebook.
var codes = new byte[8];
codes[0] = alpha0;
codes[1] = alpha1;
if (alpha0 <= alpha1) {
// Use the 5-alpha codebook.
for (int i = 1; i < 5; ++i)
codes[1 + i] = (byte)(((5 - i) * alpha0 + i * alpha1) / 5);
codes[6] = 0;
codes[7] = 255;
} else {
// Use the 7-alpha codebook.
for (int i = 1; i < 7; ++i)
codes[1 + i] = (byte)(((7 - i) * alpha0 + i * alpha1) / 7);
}
// Decode the incdices
var indices = new byte[16];
var blOff = 2;
var indOff = 0;
for (int i = 0; i < 2; ++i) {
// Grab 3 bytes
int value = 0;
for (int j = 0; j < 3; ++j) {
var b = block[blockOffset + blOff++];
value |= (b << 8 * j);
}
// Unpack 8 3-bit values from it
for (int j = 0; j < 8; ++j) {
var index = (value >> 3 * j) & 0x7;
indices[indOff++] = (byte)index;
}
}
// Write out the index codebook values.
for (int i = 0; i < 16; ++i)
target[targetOffset + 4 * i + 3] = codes[indices[i]];
}
#endregion
}
}
================================================
FILE: DotSquish/ClusterFit.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotSquish {
internal class ClusterFit : ColourFit {
const int MaxIterations = 8;
#region Fields
private int _IterationCount;
private Vector3 _Principle;
private byte[] _Order = new byte[16 * MaxIterations];
private Vector4[] _PointsWeight = new Vector4[16];
private Vector4 _XSumWSum;
private Vector4 _Metric;
private Vector4 _BestError;
#endregion
#region Constructor
protected ClusterFit(ColourSet colours, SquishOptions flags) : base(colours, flags) {
// Set the iteration count.
this._IterationCount = flags.HasFlag(SquishOptions.ColourIterativeClusterFit) ? MaxIterations : 1;
// Initialise the best error.
this._BestError = new Vector4(float.MaxValue);
// Initialize the metric
var perceptual = flags.HasFlag(SquishOptions.ColourMetricPerceptual);
if (perceptual)
this._Metric = new Vector4(0.2126f, 0.7152f, 0.0722f, 0.0f);
else
this._Metric = new Vector4(1.0f);
// Get the covariance matrix.
var covariance = Sym3x3.ComputeWeightedCovariance(colours.Count, colours.Points, colours.Weights);
// Compute the principle component
this._Principle = Sym3x3.ComputePrincipledComponent(covariance);
}
#endregion
#region Methods
protected bool ConstructOrdering(Vector3 axis, int iteration) {
// Build the list of dot products.
var dps = new float[16];
var ordOff = 16 * iteration;
for (int i = 0; i < _Colours.Count; ++i) {
dps[i] = Vector3.Dot(_Colours.Points[i], axis);
this._Order[ordOff + i] = (byte)i;
}
// Stable sort using them.
for (int i = 0; i < _Colours.Count; ++i) {
for (int j = i; j > 0 && dps[j] < dps[j - 1]; --j) {
var _dps = dps[j];
var _order = _Order[ordOff + j];
dps[j] = dps[j - 1];
dps[j - 1] = _dps;
_Order[ordOff + j] = _Order[ordOff + j - 1];
_Order[ordOff + j - 1] = _order;
}
}
// Check this ordering is unique
for (int it = 0; it < iteration; ++it) {
var prevOff = 16 * it;
var same = true;
for (int i = 0; i < _Colours.Count; ++i) {
if (_Order[ordOff + i] != _Order[prevOff + i]) {
same = false;
break;
}
}
if (same)
return false;
}
// Copy the ordering and weight all the points
this._XSumWSum = new Vector4(0f);
for (int i = 0; i < _Colours.Count; ++i) {
var j = _Order[ordOff + i];
var p = new Vector4(_Colours.Points[j].X, _Colours.Points[j].Y, _Colours.Points[j].Z, 1f);
var w = new Vector4(_Colours.Weights[j]);
var x = p * w;
this._PointsWeight[i] = x;
this._XSumWSum += x;
}
return true;
}
protected override void Compress3(byte[] block) {
// Declare variables
var count = _Colours.Count;
var zero = new Vector4(0f);
var half = new Vector4(.5f);
var one = new Vector4(1f);
var two = new Vector4(2f);
var half_half2 = new Vector4(.5f, .5f, .5f, .25f);
var grid = new Vector4(31f, 63f, 31f, 0f);
var gridrcp = new Vector4(1f / 31f, 1f / 63f, 1f / 31f, 0f);
// Prepare the ordering using the principle axis.
ConstructOrdering(_Principle, 0);
// Check all possible clusters and iterate on the total order.
var bestStart = zero;
var bestEnd = zero;
var bestError = this._BestError;
var bestIndices = new byte[16];
//var bestIteration = 0;
//int besti = 0, bestj = 0;
//// Loop over iterations (we avoid the case that all points in first or last cluster)
//for (int iterationIndex = 0; ; ) {
// throw new NotImplementedException();
//}
throw new NotImplementedException();
}
protected override void Compress4(byte[] block) {
throw new NotImplementedException();
}
#endregion
}
}
================================================
FILE: DotSquish/ColourBlock.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotSquish {
internal static class ColourBlock {
private static int Unpack565(byte[] packed, int packedOffset, byte[] colour, int colourOffset) {
// Build the packed value.
var value = (int)packed[packedOffset] | ((int)packed[packedOffset + 1] << 8);
// Get the components in the stored range.
var red = (byte)((value >> 11) & 0x1F);
var green = (byte)((value >> 5) & 0x3F);
var blue = (byte)(value & 0x1F);
// Scale up to 8 bits
colour[colourOffset + 0] = (byte)((red << 3) | (red >> 2));
colour[colourOffset + 1] = (byte)((green << 2) | (green >> 4));
colour[colourOffset + 2] = (byte)((blue << 3) | (blue >> 2));
colour[colourOffset + 3] = 255;
return value;
}
public static byte[] DecompressColour(byte[] block, int blockOffset, bool isDxt1) {
// Unpack the endpoints
var codes = new byte[16];
var a = Unpack565(block, blockOffset + 0, codes, 0);
var b = Unpack565(block, blockOffset + 2, codes, 4);
// Generate the midpoints.
for (int i = 0; i < 3; ++i) {
var c = codes[i];
var d = codes[4 + i];
if (isDxt1 && a <= b) {
codes[8 + i] = (byte)((c + d) / 2);
codes[12 + i] = 0;
} else {
codes[8 + i] = (byte)(((2 * c) + d) / 3);
codes[12 + i] = (byte)((c + (2 * d)) / 3);
}
}
// Fill in alpha for the intermediate values.
codes[8 + 3] = 255;
codes[12 + 3] = (byte)((isDxt1 && a <= b) ? 0 : 255);
// Unpack the indices
var indices = new byte[16];
for (int i = 0; i < 4; i++) {
var packed = block[blockOffset + 4 + i];
indices[4 * i + 0] = (byte)(packed & 0x3);
indices[4 * i + 1] = (byte)((packed >> 2) & 0x3);
indices[4 * i + 2] = (byte)((packed >> 4) & 0x3);
indices[4 * i + 3] = (byte)((packed >> 6) & 0x3);
}
// Store the colours
var rgba = new byte[4 * 16];
for (int i = 0; i < 16; ++i) {
var offset = 4 * indices[i];
for (int j = 0; j < 4; ++j)
rgba[4 * i + j] = codes[offset + j];
}
return rgba;
}
}
}
================================================
FILE: DotSquish/ColourFit.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotSquish {
internal abstract class ColourFit {
#region Fields
protected ColourSet _Colours;
private SquishOptions _Flags;
#endregion
#region Constructor
protected ColourFit(ColourSet colours, SquishOptions flags) {
this._Colours = colours;
this._Flags = flags;
}
#endregion
#region Public
public void Compress(ref byte[] block) {
if (this._Flags.HasFlag(SquishOptions.DXT1)) {
Compress3(block);
if (!this._Colours.IsTransparent)
Compress4(block);
} else
Compress4(block);
}
#endregion
#region Protected
protected abstract void Compress3(byte[] block);
protected abstract void Compress4(byte[] block);
#endregion
}
}
================================================
FILE: DotSquish/ColourSet.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotSquish {
internal class ColourSet {
#region Fields
private int _Count = 0;
private Vector3[] _Points = new Vector3[16];
private float[] _Weights = new float[16];
private int[] _Remap = new int[16];
private bool _IsTransparent = false;
#endregion
#region Properties
public int Count { get { return this._Count; } }
public Vector3[] Points { get { return this._Points; } }
public float[] Weights { get { return this._Weights; } }
public bool IsTransparent { get { return this._IsTransparent; } }
#endregion
#region Constructor
public ColourSet(byte[] rgba, int mask, SquishOptions flags) {
// Check the compression mode.
var isDxt1 = flags.HasFlag(SquishOptions.DXT1);
var weightByAlpha = flags.HasFlag(SquishOptions.WeightColourByAlpha);
// Create he minimal set.
for (int i = 0; i < 16; ++i) {
// Check this pixel is enabled.
int bit = 1 << i;
if ((mask & bit) == 0) {
this._Remap[i] = -1;
continue;
}
// Check for transparent pixels when using DXT1.
if (isDxt1 && rgba[4 * i + 3] < 128) {
this._Remap[i] = -1;
this._IsTransparent = true;
}
// Loop over previous points for a match.
for (int j = 0; ; ++j) {
// Allocate a new point.
if (j == i) {
// Normalise coordinates to [0,1].
var x = rgba[4 * i] / 255f;
var y = rgba[4 * i + 1] / 255f;
var z = rgba[4 * i + 2] / 255f;
// Ensure there is always a non-zero weight even for zero alpha.
var w = (rgba[4 * i + 3] + 1) / 256f;
// Add the point.
this._Points[this._Count] = new Vector3(x, y, z);
this._Weights[this._Count] = w;
this._Remap[i] = this._Count;
// Advance.
++this._Count;
break;
}
// Check for a match.
int oldBit = 1 << j;
var match = ((mask & oldBit) != 0)
&& (rgba[4 * i] == rgba[4 * j])
&& (rgba[4 * i + 1] == rgba[4 * j + 1])
&& (rgba[4 * i + 3] == rgba[4 * j + 2])
&& (rgba[4 * j + 3] >= 128 || !isDxt1);
if (match) {
// Get index of the match.
var index = this._Remap[j];
// Ensure there is always a non-zero weight even for zero alpha.
var w = (rgba[4 * i + 3] + 1) / 256f;
// Map this point and increase the weight.
this._Weights[index] += (weightByAlpha ? w : 1f);
this._Remap[i] = index;
break;
}
}
}
// Square root the weights.
for (int i = 0; i < this._Count; ++i)
this._Weights[i] = (float)Math.Sqrt(this._Weights[i]);
}
#endregion
#region Methods
public void RemapIndices(byte[] source, byte[] target, int targetOffset) {
for (int i = 0; i < 16; ++i) {
var j = this._Remap[i];
if (j == -1)
target[i + targetOffset] = 3;
else
target[i + targetOffset] = source[j];
}
}
#endregion
}
}
================================================
FILE: DotSquish/DotSquish.csproj
================================================
{F9681545-4BEA-4FD3-9AB9-A67BD37AB36D}
net7.0
bin\$(Configuration)\
true
full
pdbonly
================================================
FILE: DotSquish/Flags.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotSquish {
[Flags]
public enum SquishOptions {
///
/// Use DXT1 compression.
///
DXT1 = (1 << 0),
///
/// Use DXT3 compression.
///
DXT3 = (1 << 1),
///
/// Use DXT5 compression.
///
DXT5 = (1 << 2),
///
/// Use a very slow but very high quality colour compressor.
///
ColourIterativeClusterFit = (1 << 3),
///
/// Use a slow but high quality colour compressor (default).
///
ColourClusterFit = (1 << 4),
///
/// Use a fast but low quality colour compressor.
///
ColourRangeFit = (1 << 5),
///
/// Use a perceptual metric for colour error (default).
///
ColourMetricPerceptual = (1 << 6),
///
/// Use a uniform metric for colour error.
///
ColourMetricUniform = (1 << 7),
///
/// Weight the colour by alpha during cluster fit (off by default).
///
WeightColourByAlpha = (1 << 8),
}
public static class SquishOptionsExtensions {
public static SquishOptions GetMethod(this SquishOptions self) {
return (self & (SquishOptions.DXT1 | SquishOptions.DXT3 | SquishOptions.DXT5));
}
public static SquishOptions GetFit(this SquishOptions self) {
return (self & (SquishOptions.ColourIterativeClusterFit | SquishOptions.ColourClusterFit | SquishOptions.ColourRangeFit));
}
public static SquishOptions GetMetric(this SquishOptions self) {
return (self & (SquishOptions.ColourMetricPerceptual | SquishOptions.ColourMetricUniform));
}
public static SquishOptions GetExtra(this SquishOptions self) {
return (self & (SquishOptions.WeightColourByAlpha));
}
}
}
================================================
FILE: DotSquish/Maths.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotSquish {
internal struct Vector3 {
public float X, Y, Z;
public Vector3(float value) {
this.X = this.Y = this.Z = value;
}
public Vector3(float x, float y, float z) {
this.X = x;
this.Y = y;
this.Z = z;
}
public static Vector3 operator +(Vector3 v1, Vector3 v2) {
return new Vector3(
v1.X + v2.X,
v1.Y + v2.Y,
v1.Z + v2.Z);
}
public static Vector3 operator -(Vector3 v) {
return new Vector3(
- v.X,
- v.Y,
- v.Z);
}
public static Vector3 operator -(Vector3 v1, Vector3 v2) {
return new Vector3(
v1.X - v2.X,
v1.Y - v2.Y,
v1.Z - v2.Z);
}
public static Vector3 operator *(Vector3 v1, Vector3 v2) {
return new Vector3(
v1.X * v2.X,
v1.Y * v2.Y,
v1.Z * v2.Z);
}
public static Vector3 operator *(Vector3 v1, float v2) {
return new Vector3(
v1.X * v2,
v1.Y * v2,
v1.Z * v2);
}
public static Vector3 operator *(float v1, Vector3 v2) {
return (v2 * v1);
}
public static Vector3 operator /(Vector3 v1, Vector3 v2) {
return new Vector3(
v1.X / v2.X,
v1.Y / v2.Y,
v1.Z / v2.Z);
}
public static Vector3 operator /(Vector3 v1, float v2) {
return new Vector3(
v1.X / v2,
v1.Y / v2,
v1.Z / v2);
}
public static float Dot(Vector3 v1, Vector3 v2) {
return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z;
}
public static Vector3 Min(Vector3 v1, Vector3 v2) {
return new Vector3(
(float)Math.Min(v1.X, v2.X),
(float)Math.Min(v1.Y, v2.Y),
(float)Math.Min(v1.Z, v2.Z));
}
public static Vector3 Max(Vector3 v1, Vector3 v2) {
return new Vector3(
(float)Math.Max(v1.X, v2.X),
(float)Math.Max(v1.Y, v2.Y),
(float)Math.Max(v1.Z, v2.Z));
}
public static Vector3 Max(Vector3 v) {
return new Vector3(
(float)(v.X > 0f ? Math.Floor(v.X) : Math.Ceiling(v.X)),
(float)(v.Y > 0f ? Math.Floor(v.Y) : Math.Ceiling(v.Y)),
(float)(v.Z > 0f ? Math.Floor(v.Z) : Math.Ceiling(v.Z)));
}
}
internal struct Vector4 {
public float X, Y, Z, W;
public Vector4(float value) {
this.X = this.Y = this.Z = this.W = value;
}
public Vector4(float x, float y, float z, float w) {
this.X = x;
this.Y = y;
this.Z = z;
this.W = w;
}
public static Vector4 operator +(Vector4 v1, Vector4 v2) {
return new Vector4(
v1.X + v2.X,
v1.Y + v2.Y,
v1.Z + v2.Z,
v1.W + v2.W);
}
public static Vector4 operator -(Vector4 v) {
return new Vector4(
-v.X,
-v.Y,
-v.Z,
-v.W);
}
public static Vector4 operator -(Vector4 v1, Vector4 v2) {
return new Vector4(
v1.X - v2.X,
v1.Y - v2.Y,
v1.Z - v2.Z,
v1.W - v2.W);
}
public static Vector4 operator *(Vector4 v1, Vector4 v2) {
return new Vector4(
v1.X * v2.X,
v1.Y * v2.Y,
v1.Z * v2.Z,
v1.W * v2.W);
}
public static Vector4 operator *(Vector4 v1, float v2) {
return new Vector4(
v1.X * v2,
v1.Y * v2,
v1.Z * v2,
v1.W * v2);
}
public static Vector4 operator *(float v1, Vector4 v2) {
return (v2 * v1);
}
public static Vector4 operator /(Vector4 v1, Vector4 v2) {
return new Vector4(
v1.X / v2.X,
v1.Y / v2.Y,
v1.Z / v2.Z,
v1.W / v2.W);
}
public static Vector4 operator /(Vector4 v1, float v2) {
return new Vector4(
v1.X / v2,
v1.Y / v2,
v1.Z / v2,
v1.W / v2);
}
}
internal class Sym3x3 {
private float[] _X = new float[6];
public float this[int index] {
get { return this._X[index]; }
set { this._X[index] = value; }
}
public Sym3x3() { }
public Sym3x3(float s) {
for (int i = 0; i < 6; ++i)
this._X[i] = s;
}
public static Sym3x3 ComputeWeightedCovariance(int n, Vector3[] points, float[] weights) {
// Compute the centroid.
var total = 0f;
var centroid = new Vector3(0f);
for (int i = 0; i < n; ++i) {
total += weights[i];
centroid += weights[i] * points[i];
}
centroid /= total;
// Accumulate the covariance matrix.
var covariance = new Sym3x3(0f);
for (int i = 0; i < n; ++i) {
var a = points[i] - centroid;
var b = weights[i] * a;
covariance[0] += a.X * b.X;
covariance[1] += a.X * b.Y;
covariance[2] += a.X * b.Z;
covariance[3] += a.Y * b.Y;
covariance[4] += a.Y * b.Z;
covariance[5] += a.Z * b.Z;
}
return covariance;
}
private static Vector3 GetMultiplicity1Evector(Sym3x3 matrix, float evalue) {
// Compute M
var m = new Sym3x3();
m[0] = matrix[0] - evalue;
m[1] = matrix[1];
m[2] = matrix[2];
m[3] = matrix[3] - evalue;
m[4] = matrix[4];
m[5] = matrix[5] - evalue;
// Compute U
var u = new Sym3x3();
u[0] = (m[3] * m[5]) - (m[4] * m[4]);
u[1] = (m[2] * m[4]) - (m[1] * m[5]);
u[2] = (m[1] * m[4]) - (m[2] * m[3]);
u[3] = (m[0] * m[5]) - (m[2] * m[2]);
u[4] = (m[1] * m[2]) - (m[4] * m[0]);
u[5] = (m[0] * m[3]) - (m[1] * m[1]);
// Find the largest component.
var mc = Math.Abs(u[0]);
var mi = 0;
for (int i = 1; i < 6; ++i) {
var c = Math.Abs(u[i]);
if (c > mc) {
mc = c;
mi = i;
}
}
// Pick the column with this component.
switch (mi) {
case 0:
return new Vector3(u[0], u[1], u[2]);
case 1:
case 3:
return new Vector3(u[1], u[3], u[4]);
default:
return new Vector3(u[2], u[4], u[5]);
}
}
private static Vector3 GetMultiplicity2Evector(Sym3x3 matrix, float evalue) {
// Compute M
var m = new Sym3x3();
m[0] = matrix[0] - evalue;
m[1] = matrix[1];
m[2] = matrix[2];
m[3] = matrix[3] - evalue;
m[4] = matrix[4];
m[5] = matrix[5] - evalue;
// Find the largest component.
var mc = Math.Abs(m[0]);
var mi = 0;
for (int i = 1; i < 6; ++i) {
var c = Math.Abs(m[i]);
if (c > mc) {
mc = c;
mi = i;
}
}
// pick the first eigenvector based on this index
switch (mi) {
case 0:
case 1:
return new Vector3(-m[1], m[0], 0.0f);
case 2:
return new Vector3(m[2], 0.0f, -m[0]);
case 3:
case 4:
return new Vector3(0.0f, -m[4], m[3]);
default:
return new Vector3(0.0f, -m[5], m[4]);
}
}
public static Vector3 ComputePrincipledComponent(Sym3x3 matrix) {
// Compute the cubic coefficients
var c0 =
(matrix[0] * matrix[3] * matrix[5])
+ (matrix[1] * matrix[2] * matrix[4] * 2f)
- (matrix[0] * matrix[4] * matrix[4])
- (matrix[3] * matrix[2] * matrix[2])
- (matrix[5] * matrix[1] * matrix[1]);
var c1 =
(matrix[0] * matrix[3])
+ (matrix[0] * matrix[5])
+ (matrix[3] * matrix[5])
- (matrix[1] * matrix[1])
- (matrix[2] * matrix[2])
- (matrix[4] * matrix[4]);
var c2 = matrix[0] + matrix[3] + matrix[5];
// Compute the quadratic coefficients
var a = c1 - ((1f / 3f) * c2 * c2);
var b = ((-2f / 27f) * c2 * c2 * c2) + ((1f / 3f) * c1 * c2) - c0;
// Compute the root count check;
var Q = (.25f * b * b) + ((1f / 27f) * a * a * a);
// Test the multiplicity.
if (float.Epsilon < Q)
return new Vector3(1f); // Only one root, which implies we have a multiple of the identity.
else if (Q < -float.Epsilon) {
// Three distinct roots
var theta = Math.Atan2(Math.Sqrt(Q), -.5f * b);
var rho = Math.Sqrt((.25f * b * b) - Q);
var rt = Math.Pow(rho, 1f / 3f);
var ct = Math.Cos(theta / 3f);
var st = Math.Sin(theta / 3f);
var l1 = ((1f / 3f) * c2) + (2f * rt * ct);
var l2 = ((1f / 3f) * c2) - (rt * (ct + (Math.Sqrt(3f) * st)));
var l3 = ((1f / 3f) * c2) - (rt * (ct - (Math.Sqrt(3f) * st)));
// Pick the larger.
if (Math.Abs(l2) > Math.Abs(l1))
l1 = l2;
if (Math.Abs(l3) > Math.Abs(l1))
l1 = l3;
// Get the eigenvector
return GetMultiplicity1Evector(matrix, (float)l1);
} else { // Q very close to 0
// Two roots
double rt;
if (b < 0.0f)
rt = -Math.Pow(-.5f * b, 1f / 3f);
else
rt = Math.Pow(.5f * b, 1f / 3f);
var l1 = ((1f / 3f) * c2) + rt;
var l2 = ((1f / 3f) * c2) - (2f * rt);
// Get the eigenvector
if (Math.Abs(l1) > Math.Abs(l2))
return GetMultiplicity2Evector(matrix, (float)l1);
else
return GetMultiplicity1Evector(matrix, (float)l2);
}
}
}
}
================================================
FILE: DotSquish/Squish.cs
================================================
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotSquish {
public static class Squish {
public static int GetStorageRequirements(int width, int height, SquishOptions flags) {
var blockCount = ((width + 3) / 4) * ((height + 3) / 4);
var blockSize = flags.HasFlag(SquishOptions.DXT1) ? 8 : 16;
return blockCount * blockSize;
}
#region On buffer
public static byte[] CompressBlock(byte[] rgba, SquishOptions flags) {
return CompressBlockMasked(rgba, 0xFFFF, flags);
}
public static byte[] CompressBlockMasked(byte[] rgba, int mask, SquishOptions flags) {
throw new NotImplementedException();
}
public static byte[] DecompressBlock(byte[] block, int blockOffset, SquishOptions flags) {
// Get the block locations
var colOff = blockOffset;
var alphaOff = blockOffset;
if ((flags & (SquishOptions.DXT3 | SquishOptions.DXT5)) != 0)
colOff += 8;
// Decompress colour.
var rgba = ColourBlock.DecompressColour(block, colOff, flags.HasFlag(SquishOptions.DXT1));
// Decompress alpha seperately if necessary.
if (flags.HasFlag(SquishOptions.DXT3))
Alpha.DecompressAlphaDxt3(block, alphaOff, rgba, 0);
else if (flags.HasFlag(SquishOptions.DXT5))
Alpha.DecompressAlphaDxt5(block, alphaOff, rgba, 0);
return rgba;
}
public static byte[] CompressImage(byte[] rgba, int width, int height, SquishOptions flags) {
throw new NotImplementedException();
}
public static byte[] DecompressImage(byte[] blocks, int width, int height, SquishOptions flags) {
return DecompressImage(blocks, 0, width, height, flags);
}
public static byte[] DecompressImage(byte[] blocks, int offset, int width, int height, SquishOptions flags) {
var argb = new byte[4 * width * height];
var bytesPerBlock = flags.HasFlag(SquishOptions.DXT1) ? 8 : 16;
var blockOffset = offset;
// Loop over blocks.
for (int y = 0; y < height; y += 4) {
for (int x = 0; x < width; x += 4) {
// Decompress the block.
var targetRgba = DecompressBlock(blocks, blockOffset, flags);
// Write the decompressed pixels to the correct image locations.
var sourcePixelOffset = 0;
for (int py = 0; py < 4; ++py) {
for (int px = 0; px < 4; ++px) {
// Get the target location.
var sx = x + px;
var sy = y + py;
if (sx < width && sy < height) {
var targetPixelOffset = 4 * ((width * sy) + sx);
// Copy the rgba value
argb[targetPixelOffset + 0] = targetRgba[sourcePixelOffset + 2];
argb[targetPixelOffset + 1] = targetRgba[sourcePixelOffset + 1];
argb[targetPixelOffset + 2] = targetRgba[sourcePixelOffset + 0];
argb[targetPixelOffset + 3] = targetRgba[sourcePixelOffset + 3];
}
sourcePixelOffset += 4;
}
}
// advance
blockOffset += bytesPerBlock;
}
}
return argb;
}
public static Image DecompressToBitmap(byte[] blocks, int width, int height, SquishOptions flags) {
return DecompressToBitmap(blocks, 0, width, height, flags);
}
public static unsafe Image DecompressToBitmap(byte[] blocks, int offset, int width, int height, SquishOptions flags) {
var fullBuffer = new byte[4 * width * height];
var bufferOffset = 0;
var bytesPerBlock = flags.HasFlag(SquishOptions.DXT1) ? 8 : 16;
var blockOffset = offset;
// Loop over blocks.
for (int y = 0; y < height; y += 4) {
for (int x = 0; x < width; x += 4) {
// Decompress the block.
var targetRgba = DecompressBlock(blocks, blockOffset, flags);
// Write the decompressed pixels to the correct image locations.
var sourcePixelOffset = 0;
for (int py = 0; py < 4; ++py) {
for (int px = 0; px < 4; ++px) {
// Get the target location.
var sx = x + px;
var sy = y + py;
if (sx < width && sy < height) {
var i = 4 * (sx + (sy * width));
fullBuffer[bufferOffset + i + 0] = targetRgba[sourcePixelOffset + 2];
fullBuffer[bufferOffset + i + 1] = targetRgba[sourcePixelOffset + 1];
fullBuffer[bufferOffset + i + 2] = targetRgba[sourcePixelOffset + 0];
fullBuffer[bufferOffset + i + 3] = targetRgba[sourcePixelOffset + 3];
}
sourcePixelOffset += 4; // Skip this pixel as it is outside the image.
}
}
// advance
blockOffset += bytesPerBlock;
}
}
Image ret;
fixed (byte* p = fullBuffer) {
var ptr = (IntPtr)p;
var tempImage = new Bitmap(width, height, 4 * width, System.Drawing.Imaging.PixelFormat.Format32bppArgb, ptr);
ret = new Bitmap(tempImage);
}
return ret;
}
#endregion
#region On stream
public static void CompressBlock(Stream input, Stream output, SquishOptions flags) {
CompressBlockMasked(input, output, 0xFFFF, flags);
}
public static void CompressBlockMasked(Stream input, Stream output, int mask, SquishOptions flags){
throw new NotImplementedException();
}
public static void DecompressBlock(Stream input, Stream output, SquishOptions flags) {
throw new NotImplementedException();
}
public static void CompressImage(Stream input, Stream output, int width, int height, SquishOptions flags) {
throw new NotImplementedException();
}
public static void DecompressImage(Stream input, Stream output, int width, int height, SquishOptions flags) {
throw new NotImplementedException();
}
#endregion
}
}
================================================
FILE: Godbert/App.config
================================================
================================================
FILE: Godbert/App.xaml
================================================
================================================
FILE: Godbert/App.xaml.cs
================================================
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using Ookii.Dialogs.Wpf;
namespace Godbert {
///
/// Interaction logic for App.xaml
///
public partial class App : Application {
protected override void OnStartup(StartupEventArgs e) {
if (!RequestGamePath()) {
MainWindow = null;
Shutdown(1);
return;
}
SaintCoinach.Graphics.Viewer.Interop.HavokInterop.InitializeMTA();
base.OnStartup(e);
this.Exit += App_Exit;
}
private void App_Exit(object sender, ExitEventArgs e) {
Settings.Default.Save();
}
#region Startup
private static bool RequestGamePath() {
string path = Godbert.Properties.Settings.Default.GamePath;
if (!IsValidGamePath(path)) {
string programDir;
if (Environment.Is64BitProcess)
programDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
else
programDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
path = System.IO.Path.Combine(programDir, "SquareEnix", "FINAL FANTASY XIV - A Realm Reborn");
if (IsValidGamePath(path)) {
var msgResult = System.Windows.MessageBox.Show(string.Format("Found game installation at \"{0}\". Is this correct?", path), "Confirm game installation", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes);
if (msgResult == MessageBoxResult.Yes) {
Godbert.Properties.Settings.Default.GamePath = path;
Godbert.Properties.Settings.Default.Save();
return true;
}
path = null;
}
}
VistaFolderBrowserDialog dlg = null;
while (!IsValidGamePath(path)) {
var result = (dlg ?? (dlg = new VistaFolderBrowserDialog {
Description = "Please select the directory of your FFXIV:ARR game installation (should contain 'boot' and 'game' directories).",
ShowNewFolderButton = false,
})).ShowDialog();
if (!result.GetValueOrDefault(false)) {
var msgResult = System.Windows.MessageBox.Show("Cannot continue without a valid game installation, quit the program?", "That's no good", MessageBoxButton.YesNo, MessageBoxImage.Error, MessageBoxResult.No);
if (msgResult == MessageBoxResult.Yes)
return false;
}
path = dlg.SelectedPath;
}
Godbert.Properties.Settings.Default.GamePath = path;
Godbert.Properties.Settings.Default.Save();
return true;
}
public static bool IsValidGamePath(string path) {
if (string.IsNullOrWhiteSpace(path))
return false;
if (!Directory.Exists(path))
return false;
return File.Exists(Path.Combine(path, "game", "ffxivgame.ver"));
}
#endregion
}
}
================================================
FILE: Godbert/Commands/DelegateCommand.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Godbert.Commands {
public class DelegateCommand : System.Windows.Input.ICommand {
#region Fields
private Action _Target;
#endregion
#region Constructor
public DelegateCommand(Action target) {
_Target = target;
}
#endregion
#region ICommand Members
public bool CanExecute(object parameter) {
return true;
}
public void Execute(object parameter) {
_Target();
}
#endregion
#region ICommand Members
event EventHandler System.Windows.Input.ICommand.CanExecuteChanged {
add { }
remove { }
}
#endregion
}
public class DelegateCommand : System.Windows.Input.ICommand {
#region Fields
private Action _Target;
#endregion
#region Constructor
public DelegateCommand(Action target) {
_Target = target;
}
#endregion
#region ICommand Members
public bool CanExecute(object parameter) {
return parameter == null || (parameter is T);
}
public void Execute(object parameter) {
_Target((T)parameter);
}
#endregion
#region ICommand Members
event EventHandler System.Windows.Input.ICommand.CanExecuteChanged {
add { }
remove { }
}
#endregion
}
}
================================================
FILE: Godbert/Controls/AttachedImage.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Godbert.Controls {
public static class AttachedImage {
public static readonly DependencyProperty ImageProperty = DependencyProperty.RegisterAttached("Image",
typeof(SaintCoinach.Imaging.ImageFile), typeof(AttachedImage), new PropertyMetadata(AttachedImageChanged));
public static readonly DependencyProperty ImageTypeProperty = DependencyProperty.RegisterAttached("ImageType",
typeof(string), typeof(AttachedImage), new PropertyMetadata(AttachedImageChanged));
public static readonly DependencyProperty UseImageTypeProperty = DependencyProperty.RegisterAttached("UseImageType",
typeof(bool), typeof(AttachedImage), new PropertyMetadata(true, AttachedImageChanged));
public static readonly DependencyProperty IsSizeRestrictedProperty = DependencyProperty.RegisterAttached("IsSizeRestricted",
typeof(bool?), typeof(AttachedImage), new PropertyMetadata(null, AttachedImageChanged));
private static readonly Dictionary> _SourceCache =
new Dictionary>();
public static bool GetUseImageType(DependencyObject o) {
return (bool)o.GetValue(UseImageTypeProperty);
}
public static void SetUseImageType(DependencyObject o, bool newValue) {
o.SetValue(UseImageTypeProperty, newValue);
}
public static bool? GetIsSizeRestricted(DependencyObject o) {
return (bool?)o.GetValue(IsSizeRestrictedProperty);
}
public static void SetIsSizeRestricted(DependencyObject o, bool? newValue) {
o.SetValue(IsSizeRestrictedProperty, newValue);
}
public static SaintCoinach.Imaging.ImageFile GetImage(DependencyObject o) {
return (SaintCoinach.Imaging.ImageFile)o.GetValue(ImageProperty);
}
public static void SetImage(DependencyObject o, SaintCoinach.Imaging.ImageFile v) {
o.SetValue(ImageProperty, v);
}
public static string GetImageType(DependencyObject o) {
return (string)o.GetValue(ImageTypeProperty);
}
public static void SetImageType(DependencyObject o, string v) {
o.SetValue(ImageTypeProperty, v);
}
private static void AttachedImageChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) {
var img = (Image)o;
var srcImage = GetImage(o);
var srcImageType = GetImageType(o);
var useSrcImageType = GetUseImageType(o);
if (!useSrcImageType)
srcImageType = null;
double w = double.PositiveInfinity, h = double.PositiveInfinity;
if (srcImage != null) {
var useImage = GetImageOfType(srcImage, srcImageType);
w = useImage.Width;
h = useImage.Height;
img.Source = GetAsImageSource(useImage);
} else
img.Source = null;
var sizeRestrict = GetIsSizeRestricted(o);
if (sizeRestrict.HasValue) {
if (sizeRestrict.Value == false)
w = h = double.PositiveInfinity;
img.MaxWidth = w;
img.MaxHeight = h;
}
}
private static ImageSource GetAsImageSource(SaintCoinach.Imaging.ImageFile file) {
if (file == null)
return null;
var key = file.Path;
WeakReference targetRef;
ImageSource target;
if (!_SourceCache.TryGetValue(key, out targetRef) || !targetRef.TryGetTarget(out target)) {
target = CreateSource(file);
if (targetRef == null)
_SourceCache.Add(key, new WeakReference(target));
else
targetRef.SetTarget(target);
}
return target;
}
private static SaintCoinach.Imaging.ImageFile GetImageOfType(SaintCoinach.Imaging.ImageFile original,
string type) {
if (string.IsNullOrWhiteSpace(type))
return original;
if (!original.Path.StartsWith("ui/icon/"))
return original; // XXX: Exception instead?
var dirPath = original.Path.Substring(0, "ui/icon/000000/".Length);
var targetPath = string.Format("{0}{1}/{2}", dirPath, type, original.Path.Split('/').Last());
SaintCoinach.IO.File typeFile;
if (original.Pack.Collection.TryGetFile(targetPath, out typeFile))
return (SaintCoinach.Imaging.ImageFile)typeFile;
return original;
}
private static ImageSource CreateSource(SaintCoinach.Imaging.ImageFile file) {
var argb = SaintCoinach.Imaging.ImageConverter.GetA8R8G8B8(file);
return BitmapSource.Create(
file.Width, file.Height,
96, 96,
PixelFormats.Bgra32, null,
argb, file.Width * 4);
}
}
}
================================================
FILE: Godbert/Controls/ColumnFactory.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using SaintCoinach.Ex.Relational;
using SaintCoinach.Ex.Relational.Definition;
using SaintCoinach.Ex;
using SaintCoinach.Ex.DataReaders;
namespace Godbert.Controls {
static class ColumnFactory {
public static DataGridColumn Create(RelationalColumn column) {
var sheetDef = column.Header.SheetDefinition;
Type defType = null;
if (sheetDef != null)
defType = sheetDef.GetValueType(column.Index);
var targetType = defType ?? column.Reader.Type;
var header = BuildHeader(column);
var binding = CreateCellBinding(column);
DataGridColumn target = null;
if (typeof(SaintCoinach.Imaging.ImageFile).IsAssignableFrom(targetType))
target = new RawDataGridImageColumn(column) {
Binding = binding,
};
else if (typeof(System.Drawing.Color).IsAssignableFrom(targetType))
target = new RawDataGridColorColumn(column) {
Binding = binding
};
target = target ?? new RawDataGridTextColumn(column) {
Binding = binding
};
target.Header = header;
target.IsReadOnly = true;
target.CanUserSort = true;
return target;
}
private static string BuildHeader(RelationalColumn column) {
var sb = new StringBuilder();
sb.Append(column.Index);
if (!string.IsNullOrWhiteSpace(column.Name))
sb.AppendFormat(": {0}", column.Name);
sb.Append(Environment.NewLine);
sb.Append(column.Reader.Type.Name);
if (column.ValueType != column.Reader.Name)
sb.AppendFormat(" > {0}", column.ValueType);
if (Settings.Default.ShowOffsets) {
if (column.Reader is PackedBooleanDataReader)
sb.AppendFormat(" [{0:X}&{1:X2}]", column.Offset, ((PackedBooleanDataReader)column.Reader).Mask);
else
sb.AppendFormat(" [{0:X}]", column.Offset);
}
return sb.ToString();
}
private static Binding CreateCellBinding(RelationalColumn column) {
return new Binding {
Converter = CellConverterInstance,
ConverterParameter = column.Index,
Mode = BindingMode.OneWay
};
}
public static bool ForceRaw;
public static readonly System.Windows.Data.IValueConverter CellConverterInstance = new CellConverter();
private class CellConverter : System.Windows.Data.IValueConverter {
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
var row = value as IRow;
if (row == null)
return null;
var i = System.Convert.ToInt32(parameter);
if (ForceRaw || RawDataGrid.ColumnSetToRaw[i])
return row.GetRaw(i);
return row[i] ?? row.GetRaw(i);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
throw new NotImplementedException();
}
#endregion
}
}
}
================================================
FILE: Godbert/Controls/INavigatable.cs
================================================
using SaintCoinach.Ex;
using SaintCoinach.Ex.Relational;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace Godbert.Controls
{
public interface INavigatable
{
IRow OnNavigate(object sender, RoutedEventArgs e);
}
}
================================================
FILE: Godbert/Controls/IRawDataColumn.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SaintCoinach.Ex.Relational;
namespace Godbert.Controls {
public interface IRawDataColumn {
IComparer