فهرست منبع

Designed a visual interface for mock-up level design tools in Sandbox.

David Piuva 5 سال پیش
والد
کامیت
7030057d08
3فایلهای تغییر یافته به همراه147 افزوده شده و 51 حذف شده
  1. 58 5
      Source/SDK/sandbox/media/interface.lof
  2. 89 40
      Source/SDK/sandbox/sandbox.cpp
  3. 0 6
      Source/SDK/sandbox/tool.cpp

+ 58 - 5
Source/SDK/sandbox/media/interface.lof

@@ -5,19 +5,72 @@ Begin : Panel
 		Name = "toolPanel"
 		Left = +0
 		Top = +0
-		Right = +70
-		Bottom = +50
+		Right = 10%+100
+		Bottom = 100%
 		Solid = 1
 		Color = 100,150,100
 		Begin : Button
-			Name = "ExitButton"
-			Text = "Exit"
+			Name = "spriteButton"
+			Text = "Sprite"
 			Left = +10
 			Top = +10
-			Right = +60
+			Right = 50%-5
 			Bottom = +40
 			Color = 200,200,200
 		End
+		Begin : Button
+			Name = "modelButton"
+			Text = "Model"
+			Left = 50%+5
+			Top = +10
+			Right = 100%-10
+			Bottom = +40
+			Color = 200,200,200
+		End
+		Begin : Panel
+			Name = "spritePanel"
+			Solid = 0
+			Top = +40
+			Begin : Button
+				Name = "leftButton"
+				Text = "<"
+				Left = +10
+				Top = +10
+				Right = 50%-5
+				Bottom = +40
+				Color = 200,200,200
+			End
+			Begin : Button
+				Name = "rightButton"
+				Text = ">"
+				Left = 50%+5
+				Top = +10
+				Right = 100%-10
+				Bottom = +40
+				Color = 200,200,200
+			End
+			Begin : ListBox
+				Name = "spriteList"
+				Left = +10
+				Top = +50
+				Right = 100%-10
+				Bottom = 100%-10
+				Color = 50,75,50
+			End
+		End
+		Begin : Panel
+			Name = "modelPanel"
+			Solid = 0
+			Top = +40
+			Begin : ListBox
+				Name = "modelList"
+				Left = +10
+				Top = +10
+				Right = 100%-10
+				Bottom = 100%-10
+				Color = 50,75,50
+			End
+		End
 	End
 End
 

+ 89 - 40
Source/SDK/sandbox/sandbox.cpp

@@ -30,6 +30,7 @@ BUGS:
 			An optional triangle patch can be added along the open sides. (all for planes and excluding sides for cylinders)
 
 VISUALS:
+	* Implement freely rotated background models in the sprite engine.
 	* Make a directed light source that casts light and shadows from a fixed direction but can fade like a point light.
 		Useful for street-lights and sky-lights that want to avoid normalizing and projecting light directions per pixel.
 		Can be used both with and without casting shadows.
@@ -71,6 +72,7 @@ VISUALS:
 		The first cubemap will be persistent and used later for dynamic light.
 		The later cubemaps will be temporary when generating the background's softer light.
 USABILITY:
+	* Tool for placing freely rotated isometric models into the background.
 	* Tool for selecting and removing passive sprites.
 		Use both unique handles for simplicity and the raw look-up for handling multiple sprites at once:
 			Given an optional integer argument (defaulted to zero) to background sprite construction.
@@ -131,13 +133,9 @@ static bool running = true;
 static IVector2D mousePos;
 static bool panorate = false;
 static bool tileAlign = false;
-static bool showOverlays = true;
 static int debugView = 0;
 static int mouseLights = 1;
 
-// The window handle
-static Window window;
-
 static int random(const int minimum, const int maximum) {
 	if (maximum > minimum) {
 		return (std::rand() % (maximum + 1 - minimum)) + minimum;
@@ -158,6 +156,29 @@ static SpriteWorld world;
 bool ambientLight = true;
 int testModelCount = 0;
 
+// GUI
+static Window window;
+Component mainPanel, spritePanel, spriteList, modelPanel, modelList;
+static int overlayMode = 2;
+	static const int OverlayMode_None = 0;
+	static const int OverlayMode_Profiling = 1;
+	static const int OverlayMode_Tools = 2;
+	static const int OverlayModeCount = 3;
+static int tool = 0;
+	static const int Tool_PlaceSprite = 0;
+	static const int Tool_PlaceModel = 1;
+	static const int ToolCount = 2;
+void updateOverlay() {
+	component_setProperty_integer(mainPanel, U"Visible", overlayMode == OverlayMode_Tools);
+		component_setProperty_integer(spritePanel, U"Visible", tool == Tool_PlaceSprite);
+		component_setProperty_integer(modelPanel, U"Visible", tool == Tool_PlaceModel);
+}
+
+void loadSprite(const ReadableString& name) {
+	sprite_loadTypeFromFile(imagePath, name);
+	component_call(spriteList, U"PushElement", name);
+}
+
 void sandbox_main() {
 	// Create the world
 	world = spriteWorld_create(OrthoSystem(string_load(string_combine(mediaPath, U"Ortho.ini"))), 256);
@@ -206,17 +227,10 @@ void sandbox_main() {
 			} else if (key == DsrKey_Y) {
 				testModelCount = (testModelCount + 1) % 11;
 			} else if (key == DsrKey_F) {
-				showOverlays = !showOverlays;
+				overlayMode = (overlayMode + 1) % OverlayModeCount;
+				updateOverlay();
 			} else if (key == DsrKey_K) {
 				mouseLights = (mouseLights + 1) % 5;
-			} else if (key == DsrKey_Q) {
-				// Previous type
-				brush.typeIndex = (brush.typeIndex + sprite_getTypeCount() - 1) % sprite_getTypeCount();
-			} else if (key == DsrKey_E) {
-				// Next type
-				brush.typeIndex = (brush.typeIndex + 1) % sprite_getTypeCount();
-			} else if (key == DsrKey_X) {
-				brush.direction = correctDirection(brush.direction + dir90);
 			} else if (key == DsrKey_C) {
 				// Rotate the world clockwise using four camera angles
 				spriteWorld_setCameraDirectionIndex(world, (spriteWorld_getCameraDirectionIndex(world) + 1) % 4);
@@ -253,11 +267,17 @@ void sandbox_main() {
 		cameraMovement.y = buttonPressed[3] - buttonPressed[2];
 	});
 	// Get component handles and assign actions
-	Component mainPanel = window_getRoot(window);
+	mainPanel = window_getRoot(window);
 	component_setMouseDownEvent(mainPanel, [](const MouseEvent& event) {
 		if (event.key == MouseKeyEnum::Left) {
-			// Place a new visual instance using the brush
-			spriteWorld_addBackgroundSprite(world, brush);
+			if (overlayMode == OverlayMode_Tools) {
+				if (tool == Tool_PlaceSprite) {
+					// Place a new visual instance using the brush
+					spriteWorld_addBackgroundSprite(world, brush);
+				} else if (tool == Tool_PlaceModel) {
+					// TODO: Implement a way to place a background model with 3-dimensional location, 3-axis rotation and uniform scaling
+				}
+			}
 		} else if (event.key == MouseKeyEnum::Right) {
 			panorate = true;
 		}
@@ -275,18 +295,46 @@ void sandbox_main() {
 		}
 	});
 
-	Component exitButton = window_findComponentByName(window, U"ExitButton");
-	component_setPressedEvent(exitButton, []() {
-		running = false;
+	mainPanel = window_findComponentByName(window, U"mainPanel");
+	spritePanel = window_findComponentByName(window, U"spritePanel");
+	modelPanel = window_findComponentByName(window, U"modelPanel");
+	component_setPressedEvent(window_findComponentByName(window, U"spriteButton"), []() {
+		tool = Tool_PlaceSprite;
+		updateOverlay();
+	});
+	component_setPressedEvent(window_findComponentByName(window, U"modelButton"), []() {
+		tool = Tool_PlaceModel;
+		updateOverlay();
+	});
+	spriteList = window_findComponentByName(window, U"spriteList");
+	component_setSelectEvent(spriteList, [](int64_t index) {
+		brush.typeIndex = index;
+	});
+	modelList = window_findComponentByName(window, U"modelList");
+	component_setSelectEvent(modelList, [](int64_t index) {
+		// TODO: Implement model selection from the list
+	});
+	component_setPressedEvent(window_findComponentByName(window, U"leftButton"), []() {
+		brush.direction = correctDirection(brush.direction + dir270);
+	});
+	component_setPressedEvent(window_findComponentByName(window, U"rightButton"), []() {
+		brush.direction = correctDirection(brush.direction + dir90);
 	});
+	updateOverlay();
 
-	// Create sprite types
-	sprite_loadTypeFromFile(imagePath, U"Floor");
-	sprite_loadTypeFromFile(imagePath, U"WoodenFloor");
-	sprite_loadTypeFromFile(imagePath, U"WoodenFence");
-	sprite_loadTypeFromFile(imagePath, U"WoodenBarrel");
-	sprite_loadTypeFromFile(imagePath, U"Pillar");
-	sprite_loadTypeFromFile(imagePath, U"Character_Mage");
+	// Create sprite types while listing their presence in the tool menu
+	loadSprite(U"Floor");
+	loadSprite(U"WoodenFloor");
+	loadSprite(U"WoodenFence");
+	loadSprite(U"WoodenBarrel");
+	loadSprite(U"Pillar");
+	loadSprite(U"Character_Mage");
+
+	// Load models
+	DenseModel barrelVisible = DenseModel_create(importer_loadModel(modelPath + U"Barrel_LowDetail.ply", true, Transform3D()));
+	Model barrelShadow = importer_loadModel(modelPath + U"Barrel_Shadow.ply", true, Transform3D());
+	//DenseModel barrelVisible = DenseModel_create(importer_loadModel(modelPath + U"Character_Mage.ply", true, Transform3D()));
+	//Model barrelShadow = importer_loadModel(modelPath + U"Character_Mage_Shadow.ply", true, Transform3D());
 
 	// Create passive sprites
 	for (int z = -300; z < 300; z++) {
@@ -318,12 +366,6 @@ void sandbox_main() {
 	float profileFrameRate = 0.0f;
 	double maxFrameTime = 0.0, lastMaxFrameTime = 0.0; // Peak per second
 
-	// Load models
-	DenseModel barrelVisible = DenseModel_create(importer_loadModel(modelPath + U"Barrel_LowDetail.ply", true, Transform3D()));
-	Model barrelShadow = importer_loadModel(modelPath + U"Barrel_Shadow.ply", true, Transform3D());
-	//DenseModel barrelVisible = DenseModel_create(importer_loadModel(modelPath + U"Character_Mage.ply", true, Transform3D()));
-	//Model barrelShadow = importer_loadModel(modelPath + U"Character_Mage_Shadow.ply", true, Transform3D());
-
 	while(running) {
 		double timer = time_getSeconds();
 		double startTime;
@@ -384,7 +426,14 @@ void sandbox_main() {
 		}
 
 		// Show the brush
-		spriteWorld_addTemporarySprite(world, brush);
+		if (overlayMode == OverlayMode_Tools) {
+			if (tool == Tool_PlaceSprite) {
+				spriteWorld_addTemporarySprite(world, brush);
+			} else if (tool == Tool_PlaceModel) {
+				// TODO: Implement preview of freely rotated background model brush
+				//spriteWorld_addTemporaryModel(world, ModelInstance(?, ?, ?));
+			}
+		}
 
 		// Test freely rotated models
 		for(int t = 0; t < testModelCount; t++) {
@@ -418,13 +467,13 @@ void sandbox_main() {
 			draw_copy(colorBuffer, spriteWorld_getLightBuffer(world));
 		}
 
-		// Overlays mode
-		if (showOverlays) {
-			startTime = time_getSeconds();
-				window_drawComponents(window);
-			debugText("Draw GUI: ", (time_getSeconds() - startTime) * 1000.0, " ms\n");
-
-			IVector2D writer = IVector2D(10, 55);
+		// Overlays
+		startTime = time_getSeconds();
+			window_drawComponents(window);
+		debugText("Draw GUI: ", (time_getSeconds() - startTime) * 1000.0, " ms\n");
+		// Profiling mode
+		if (overlayMode == OverlayMode_Profiling) {
+			IVector2D writer = IVector2D(10, 10);
 			font_printLine(colorBuffer, font_getDefault(), string_combine(U"FPS: ", profileFrameRate), writer, ColorRgbaI32(255, 255, 255, 255)); writer.y += 20;
 			font_printLine(colorBuffer, font_getDefault(), string_combine(U"avg ms: ", 1000.0f / profileFrameRate), writer, ColorRgbaI32(255, 255, 255, 255)); writer.y += 20;
 			font_printLine(colorBuffer, font_getDefault(), string_combine(U"max ms: ", 1000.0f * lastMaxFrameTime), writer, ColorRgbaI32(255, 255, 255, 255)); writer.y += 20;

+ 0 - 6
Source/SDK/sandbox/tool.cpp

@@ -1,10 +1,4 @@
 
-/*
-	TODO:
-		* Make alternative models for animated characters and damaged buildings.
-		* Make the custom rendering system able to render directly into a game with triangle culling and clipping.
-*/
-
 #include <assert.h>
 #include <limits>
 #include <functional>