Repository: godot
Issue: Material not saved after shader saved to its own file
Labels: bug,topic:editor

**Godot version:**
3.0.6

**OS/device including version:**
macOS 10.13.6

**Issue description:**
When a custom shader that's associated with a material is saved to its own file, the material is not updated on disk, causing an older version of the shader to be used the next time the project is opened (and in some cases when the scene is run), while the new version is used in the editor until the editor is closed.

**Steps to reproduce:**
Use the Godot UI for all of the following steps:
1. Create a MeshInstance in a new scene (Optional: Assign a Sphere mesh to the Mesh property to see changes)
2. Assign a "New ShaderMaterial" to the "Material Override" property (under the Geometry section)
3. Click on the shader material you've just created to open it
4. Assign a "New Shader" to the "Shader" property
5. Click on the shader you've just created and type some basic shader code like "shader_type spatial; // Version 1" (Optional: Assign e.g. a red color to ALBEDO in the fragment function to verify that your mesh is now using this shader)
6. Go back to the Shader Material you had created, and use "Save As" in the Inspector to save it to a file (save it as a .tres file).
7. Save your scene to make sure everything is saved.
8. Click on the "Shader" again in the Inspector to open the shader again
9. Use the Inspector's "Save As" menu to save the shader to its own .shader file
9. Change shader code, e.g. to "shader_type spatial; // Version 2" (Optional: Assign e.g. a green color to ALBEDO in the fragment function to verify that your mesh is now using this shader in the editor)
10. Save the scene again

If you've assigned a sphere to the MeshInstance and changed the ALBEDO color in the shader to green, now your sphere should look Green in the editor. However, if you inspect the files in your file system, you'll notice that you have two versions of the shader code now, one in the material .tres file, and the other in the .shader file. While the editor uses the shader code in the .shader file, if you close godot and reload your project, the editor will revert back to using the old version of the shader from the .tres file. (As a side note, running the scene -- without closing godot -- also seems to use the saved version of the material, though I believe I've had one case where it used the in-memory version.)

**Further analysis:**
After step 10, do the following without closing Godot:
11. Go back to the Material
12. Increase "Render Priority" to 1, then decrease it back to 0
13. Save the scene again

Now, if you inspect the files in the file system, you'll notice that the material file will be updated to point to the .shader file instead of including its own, stale shader code.

**Conclusion:**
The problem seems to be arising from the Material not being marked as dirty (for save operations) when its shader changes after the shader is saved to a file. Although the material is updated in memory correctly, because it's not marked as dirty, its resource file on disk doesn't get updated when saving the scene, until some other change is performed on the material to force it to save (e.g. manually saving it or changing some other arbitrary property of it, like "Render Priority", before saving the scene).

The solution should be very simple: a material resource should be marked as dirty whenever its shader property changes, regardless of the reason for the change.