SET QUOTED_IDENTIFIER ON; GO IF COL_LENGTH(N'dbo.Scenes', N'FloorPlanID') IS NULL ALTER TABLE dbo.Scenes ADD FloorPlanID int NULL; GO IF COL_LENGTH(N'dbo.Scenes', N'InitialFloorPlanFloorID') IS NULL ALTER TABLE dbo.Scenes ADD InitialFloorPlanFloorID int NULL; GO IF OBJECT_ID(N'dbo.FK_Scenes_FloorPlans', N'F') IS NULL ALTER TABLE dbo.Scenes WITH CHECK ADD CONSTRAINT FK_Scenes_FloorPlans FOREIGN KEY (FloorPlanID) REFERENCES dbo.FloorPlans(FloorPlanID); GO IF OBJECT_ID(N'dbo.FK_Scenes_InitialFloorPlanFloors', N'F') IS NULL ALTER TABLE dbo.Scenes WITH CHECK ADD CONSTRAINT FK_Scenes_InitialFloorPlanFloors FOREIGN KEY (InitialFloorPlanFloorID) REFERENCES dbo.FloorPlanFloors(FloorPlanFloorID); GO IF OBJECT_ID(N'dbo.SceneFloorPlanOccupancy', N'U') IS NULL BEGIN CREATE TABLE dbo.SceneFloorPlanOccupancy ( SceneFloorPlanOccupancyID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_SceneFloorPlanOccupancy PRIMARY KEY, SceneID int NOT NULL, FloorPlanID int NOT NULL, FloorPlanFloorID int NULL, CharacterID int NULL, StoryAssetID int NULL, LocationID int NOT NULL, CreatedDate datetime2 NOT NULL CONSTRAINT DF_SceneFloorPlanOccupancy_CreatedDate DEFAULT SYSUTCDATETIME(), ModifiedDate datetime2 NULL, CONSTRAINT CK_SceneFloorPlanOccupancy_OneEntity CHECK ( (CharacterID IS NOT NULL AND StoryAssetID IS NULL) OR (CharacterID IS NULL AND StoryAssetID IS NOT NULL) ), CONSTRAINT FK_SceneFloorPlanOccupancy_Scenes FOREIGN KEY (SceneID) REFERENCES dbo.Scenes(SceneID) ON DELETE CASCADE, CONSTRAINT FK_SceneFloorPlanOccupancy_FloorPlans FOREIGN KEY (FloorPlanID) REFERENCES dbo.FloorPlans(FloorPlanID), CONSTRAINT FK_SceneFloorPlanOccupancy_FloorPlanFloors FOREIGN KEY (FloorPlanFloorID) REFERENCES dbo.FloorPlanFloors(FloorPlanFloorID), CONSTRAINT FK_SceneFloorPlanOccupancy_Characters FOREIGN KEY (CharacterID) REFERENCES dbo.Characters(CharacterID), CONSTRAINT FK_SceneFloorPlanOccupancy_StoryAssets FOREIGN KEY (StoryAssetID) REFERENCES dbo.StoryAssets(StoryAssetID), CONSTRAINT FK_SceneFloorPlanOccupancy_Locations FOREIGN KEY (LocationID) REFERENCES dbo.Locations(LocationID) ); END; GO IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'UX_SceneFloorPlanOccupancy_Character' AND object_id = OBJECT_ID(N'dbo.SceneFloorPlanOccupancy')) CREATE UNIQUE INDEX UX_SceneFloorPlanOccupancy_Character ON dbo.SceneFloorPlanOccupancy(SceneID, CharacterID) WHERE CharacterID IS NOT NULL; GO IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'UX_SceneFloorPlanOccupancy_Asset' AND object_id = OBJECT_ID(N'dbo.SceneFloorPlanOccupancy')) CREATE UNIQUE INDEX UX_SceneFloorPlanOccupancy_Asset ON dbo.SceneFloorPlanOccupancy(SceneID, StoryAssetID) WHERE StoryAssetID IS NOT NULL; GO CREATE OR ALTER PROCEDURE dbo.Scene_Save @SceneID int = NULL, @ChapterID int, @SceneNumber decimal(10,2), @SceneTitle nvarchar(200), @Summary nvarchar(max) = NULL, @TimeModeID int, @StartDateTime datetime2 = NULL, @EndDateTime datetime2 = NULL, @DurationAmount decimal(10,2) = NULL, @DurationUnitID int = NULL, @RelativeTimeText nvarchar(200) = NULL, @TimeConfidenceID int, @ScenePurposeNotes nvarchar(max) = NULL, @SceneOutcomeNotes nvarchar(max) = NULL, @RevisionStatusID int, @PrimaryLocationID int = NULL, @FloorPlanID int = NULL, @InitialFloorPlanFloorID int = NULL AS BEGIN SET NOCOUNT ON; DECLARE @NextSortOrder int; IF @SceneID IS NULL OR @SceneID = 0 BEGIN SELECT @NextSortOrder = ISNULL(MAX(SortOrder), 0) + 10 FROM dbo.Scenes WHERE ChapterID = @ChapterID; INSERT dbo.Scenes (ChapterID, SceneNumber, SceneTitle, Summary, SortOrder, TimeModeID, StartDateTime, EndDateTime, DurationAmount, DurationUnitID, RelativeTimeText, TimeConfidenceID, ScenePurposeNotes, SceneOutcomeNotes, RevisionStatusID, PrimaryLocationID, FloorPlanID, InitialFloorPlanFloorID) VALUES (@ChapterID, @SceneNumber, @SceneTitle, @Summary, @NextSortOrder, @TimeModeID, @StartDateTime, @EndDateTime, @DurationAmount, @DurationUnitID, @RelativeTimeText, @TimeConfidenceID, @ScenePurposeNotes, @SceneOutcomeNotes, @RevisionStatusID, @PrimaryLocationID, @FloorPlanID, @InitialFloorPlanFloorID); SET @SceneID = CAST(SCOPE_IDENTITY() AS int); END ELSE BEGIN UPDATE dbo.Scenes SET SceneNumber = @SceneNumber, SceneTitle = @SceneTitle, Summary = @Summary, TimeModeID = @TimeModeID, StartDateTime = @StartDateTime, EndDateTime = @EndDateTime, DurationAmount = @DurationAmount, DurationUnitID = @DurationUnitID, RelativeTimeText = @RelativeTimeText, TimeConfidenceID = @TimeConfidenceID, ScenePurposeNotes = @ScenePurposeNotes, SceneOutcomeNotes = @SceneOutcomeNotes, RevisionStatusID = @RevisionStatusID, PrimaryLocationID = @PrimaryLocationID, FloorPlanID = @FloorPlanID, InitialFloorPlanFloorID = @InitialFloorPlanFloorID, UpdatedDate = SYSUTCDATETIME() WHERE SceneID = @SceneID; END SELECT @SceneID; END; GO CREATE OR ALTER PROCEDURE dbo.Scene_Get @SceneID int AS BEGIN SET NOCOUNT ON; EXEC dbo.SceneMetric_EnsureDefaults @SceneID; SELECT s.SceneID, s.ChapterID, s.SceneNumber, s.SceneTitle, s.Summary, s.POVCharacterID, s.PrimaryLocationID, s.FloorPlanID, s.InitialFloorPlanFloorID, location.LocationName AS PrimaryLocationName, location.LocationPath AS PrimaryLocationPath, s.SortOrder, s.TimeModeID, tm.TimeModeName, s.StartDateTime, s.EndDateTime, s.DurationAmount, s.DurationUnitID, du.DurationUnitName, s.RelativeTimeText, s.TimeConfidenceID, tc.TimeConfidenceName, s.ScenePurposeNotes, s.SceneOutcomeNotes, s.RevisionStatusID, rs.StatusName AS RevisionStatusName, s.CreatedDate, s.UpdatedDate, s.IsArchived FROM dbo.Scenes s INNER JOIN dbo.TimeModes tm ON tm.TimeModeID = s.TimeModeID INNER JOIN dbo.TimeConfidences tc ON tc.TimeConfidenceID = s.TimeConfidenceID INNER JOIN dbo.RevisionStatuses rs ON rs.RevisionStatusID = s.RevisionStatusID LEFT JOIN dbo.DurationUnits du ON du.DurationUnitID = s.DurationUnitID LEFT JOIN dbo.LocationPaths location ON location.LocationID = s.PrimaryLocationID WHERE s.SceneID = @SceneID AND s.IsArchived = 0; SELECT ScenePurposeTypeID FROM dbo.ScenePurposes WHERE SceneID = @SceneID; EXEC dbo.SceneMetric_ListByScene @SceneID; END; GO CREATE OR ALTER PROCEDURE dbo.Scene_FloorPlanLink_Save @SceneID int, @FloorPlanID int = NULL, @InitialFloorPlanFloorID int = NULL AS BEGIN SET NOCOUNT ON; IF @FloorPlanID IS NULL SET @InitialFloorPlanFloorID = NULL; UPDATE dbo.Scenes SET FloorPlanID = @FloorPlanID, InitialFloorPlanFloorID = @InitialFloorPlanFloorID, UpdatedDate = SYSUTCDATETIME() WHERE SceneID = @SceneID; IF @FloorPlanID IS NULL DELETE FROM dbo.SceneFloorPlanOccupancy WHERE SceneID = @SceneID; END; GO CREATE OR ALTER PROCEDURE dbo.Scene_ListByFloorPlan @FloorPlanID int AS BEGIN SET NOCOUNT ON; SELECT s.SceneID, s.ChapterID, s.SceneNumber, s.SceneTitle, s.Summary, s.POVCharacterID, s.PrimaryLocationID, s.FloorPlanID, s.InitialFloorPlanFloorID, s.SortOrder, s.TimeModeID, tm.TimeModeName, s.StartDateTime, s.EndDateTime, s.DurationAmount, s.DurationUnitID, du.DurationUnitName, s.RelativeTimeText, s.TimeConfidenceID, tc.TimeConfidenceName, s.ScenePurposeNotes, s.SceneOutcomeNotes, s.RevisionStatusID, rs.StatusName AS RevisionStatusName, s.CreatedDate, s.UpdatedDate, s.IsArchived FROM dbo.Scenes s INNER JOIN dbo.TimeModes tm ON tm.TimeModeID = s.TimeModeID INNER JOIN dbo.TimeConfidences tc ON tc.TimeConfidenceID = s.TimeConfidenceID INNER JOIN dbo.RevisionStatuses rs ON rs.RevisionStatusID = s.RevisionStatusID LEFT JOIN dbo.DurationUnits du ON du.DurationUnitID = s.DurationUnitID WHERE s.FloorPlanID = @FloorPlanID AND s.IsArchived = 0 ORDER BY s.StartDateTime, s.SceneNumber, s.SortOrder, s.SceneTitle; END; GO CREATE OR ALTER PROCEDURE dbo.FloorPlanFloor_ListByPlan @FloorPlanID int AS BEGIN SET NOCOUNT ON; SELECT FloorPlanFloorID, FloorPlanID, LocationID, Name, SortOrder, GridWidth, GridHeight, BackgroundImagePath, BackgroundImageOriginalFileName, BackgroundOpacity, BackgroundScale, BackgroundOffsetX, BackgroundOffsetY, BackgroundLocked, CreatedDate, ModifiedDate FROM dbo.FloorPlanFloors WHERE FloorPlanID = @FloorPlanID ORDER BY SortOrder, Name; END; GO CREATE OR ALTER PROCEDURE dbo.FloorPlanBlock_ListByPlan @FloorPlanID int AS BEGIN SET NOCOUNT ON; SELECT fpb.FloorPlanBlockID, fpb.FloorPlanFloorID, fpb.LocationID, COALESCE(lp.LocationName, l.LocationName) AS LocationName, COALESCE(lp.LocationPath, l.LocationName) AS LocationPath, fpb.X, fpb.Y, fpb.WidthCells, fpb.HeightCells, fpb.BlockType, fpb.LabelOverride, fpb.Notes, fpb.CreatedDate, fpb.ModifiedDate FROM dbo.FloorPlanBlocks fpb INNER JOIN dbo.FloorPlanFloors fpf ON fpf.FloorPlanFloorID = fpb.FloorPlanFloorID INNER JOIN dbo.Locations l ON l.LocationID = fpb.LocationID LEFT JOIN dbo.LocationPaths lp ON lp.LocationID = fpb.LocationID WHERE fpf.FloorPlanID = @FloorPlanID ORDER BY fpf.SortOrder, fpf.Name, fpb.Y, fpb.X; END; GO CREATE OR ALTER PROCEDURE dbo.SceneFloorPlanOccupancy_ListByScene @SceneID int AS BEGIN SET NOCOUNT ON; SELECT o.SceneFloorPlanOccupancyID, o.SceneID, o.FloorPlanID, o.FloorPlanFloorID, o.CharacterID, c.CharacterName, c.ShortName AS CharacterShortName, c.ImagePath AS CharacterImagePath, c.ThumbnailPath AS CharacterThumbnailPath, o.StoryAssetID, sa.AssetName, sa.ImagePath AS AssetImagePath, sa.ThumbnailPath AS AssetThumbnailPath, o.LocationID, COALESCE(lp.LocationName, l.LocationName) AS LocationName, COALESCE(lp.LocationPath, l.LocationName) AS LocationPath, fpf.Name AS FloorName, o.CreatedDate, o.ModifiedDate FROM dbo.SceneFloorPlanOccupancy o INNER JOIN dbo.Locations l ON l.LocationID = o.LocationID LEFT JOIN dbo.LocationPaths lp ON lp.LocationID = o.LocationID LEFT JOIN dbo.FloorPlanFloors fpf ON fpf.FloorPlanFloorID = o.FloorPlanFloorID LEFT JOIN dbo.Characters c ON c.CharacterID = o.CharacterID LEFT JOIN dbo.StoryAssets sa ON sa.StoryAssetID = o.StoryAssetID WHERE o.SceneID = @SceneID ORDER BY COALESCE(c.CharacterName, sa.AssetName); END; GO CREATE OR ALTER PROCEDURE dbo.SceneFloorPlanOccupancy_ListByFloorPlan @FloorPlanID int AS BEGIN SET NOCOUNT ON; SELECT o.SceneFloorPlanOccupancyID, o.SceneID, o.FloorPlanID, o.FloorPlanFloorID, o.CharacterID, c.CharacterName, c.ShortName AS CharacterShortName, c.ImagePath AS CharacterImagePath, c.ThumbnailPath AS CharacterThumbnailPath, o.StoryAssetID, sa.AssetName, sa.ImagePath AS AssetImagePath, sa.ThumbnailPath AS AssetThumbnailPath, o.LocationID, COALESCE(lp.LocationName, l.LocationName) AS LocationName, COALESCE(lp.LocationPath, l.LocationName) AS LocationPath, fpf.Name AS FloorName, o.CreatedDate, o.ModifiedDate FROM dbo.SceneFloorPlanOccupancy o INNER JOIN dbo.Locations l ON l.LocationID = o.LocationID LEFT JOIN dbo.LocationPaths lp ON lp.LocationID = o.LocationID LEFT JOIN dbo.FloorPlanFloors fpf ON fpf.FloorPlanFloorID = o.FloorPlanFloorID LEFT JOIN dbo.Characters c ON c.CharacterID = o.CharacterID LEFT JOIN dbo.StoryAssets sa ON sa.StoryAssetID = o.StoryAssetID WHERE o.FloorPlanID = @FloorPlanID ORDER BY o.SceneID, COALESCE(c.CharacterName, sa.AssetName); END; GO CREATE OR ALTER PROCEDURE dbo.SceneFloorPlanOccupancy_Save @SceneID int, @FloorPlanID int = NULL, @CharacterID int = NULL, @StoryAssetID int = NULL, @LocationID int = NULL AS BEGIN SET NOCOUNT ON; IF @FloorPlanID IS NULL OR @LocationID IS NULL BEGIN DELETE FROM dbo.SceneFloorPlanOccupancy WHERE SceneID = @SceneID AND ((@CharacterID IS NOT NULL AND CharacterID = @CharacterID) OR (@StoryAssetID IS NOT NULL AND StoryAssetID = @StoryAssetID)); RETURN; END; DECLARE @FloorPlanFloorID int; SELECT TOP (1) @FloorPlanFloorID = fpb.FloorPlanFloorID FROM dbo.FloorPlanBlocks fpb INNER JOIN dbo.FloorPlanFloors fpf ON fpf.FloorPlanFloorID = fpb.FloorPlanFloorID WHERE fpf.FloorPlanID = @FloorPlanID AND fpb.LocationID = @LocationID ORDER BY fpf.SortOrder, fpf.Name, fpb.Y, fpb.X; IF @FloorPlanFloorID IS NULL THROW 51000, 'Location must be placed on the selected floor plan.', 1; MERGE dbo.SceneFloorPlanOccupancy AS target USING ( SELECT @SceneID AS SceneID, @FloorPlanID AS FloorPlanID, @FloorPlanFloorID AS FloorPlanFloorID, @CharacterID AS CharacterID, @StoryAssetID AS StoryAssetID, @LocationID AS LocationID ) AS source ON target.SceneID = source.SceneID AND ((source.CharacterID IS NOT NULL AND target.CharacterID = source.CharacterID) OR (source.StoryAssetID IS NOT NULL AND target.StoryAssetID = source.StoryAssetID)) WHEN MATCHED THEN UPDATE SET FloorPlanID = source.FloorPlanID, FloorPlanFloorID = source.FloorPlanFloorID, LocationID = source.LocationID, ModifiedDate = SYSUTCDATETIME() WHEN NOT MATCHED THEN INSERT (SceneID, FloorPlanID, FloorPlanFloorID, CharacterID, StoryAssetID, LocationID) VALUES (source.SceneID, source.FloorPlanID, source.FloorPlanFloorID, source.CharacterID, source.StoryAssetID, source.LocationID); END; GO